Rebase, clippy, fmt

This commit is contained in:
durch
2023-12-07 10:43:03 +01:00
parent 07a86afb54
commit ce8718ae96
36 changed files with 1503 additions and 1455 deletions
Generated
+673 -1010
View File
File diff suppressed because it is too large Load Diff
+19 -2
View File
@@ -111,7 +111,7 @@ members = [
"tools/nymvisor",
"tools/ts-rs-cli",
"wasm/client",
# "wasm/full-nym-wasm",
# "wasm/full-nym-wasm",
"wasm/mix-fetch",
"wasm/node-tester",
]
@@ -128,7 +128,15 @@ default-members = [
"explorer-api",
]
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles"]
exclude = [
"explorer",
"contracts",
"nym-wallet",
"nym-connect/mobile/src-tauri",
"nym-connect/desktop",
"nym-vpn/ui/src-tauri",
"cpu-cycles",
]
[workspace.package]
authors = ["Nym Technologies SA"]
@@ -207,6 +215,15 @@ wasm-bindgen-futures = "0.4.37"
wasmtimer = "0.2.0"
web-sys = "0.3.63"
bls12_381 = { path = "/Users/drazen/nym/bls12_381", default-features = false, features = [
"alloc",
"pairings",
"experimental",
"zeroize",
] }
ff = { version = "0.13", default-features = false }
group = { version = "0.13", default-features = false }
# Profile settings for individual crates
[profile.release.package.nym-socks5-listener]
+13 -18
View File
@@ -7,18 +7,20 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.19"
#bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] }
bls12_381 = { path = "/Users/simon/Documents/Nym/github/andrew_bls12_381", default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] }
itertools = "0.10"
digest = "0.9"
rand = "0.8"
thiserror = "1.0"
sha2 = "0.9"
bls12_381 = { workspace = true }
bs58 = "0.4.0"
serde = "1.0.189"
chrono = "0.4.19"
digest = "0.9"
ff = { workspace = true }
getset = "0.1.1"
zeroize = "1.6.0"
group = { workspace = true }
itertools = "0.10"
rand = "0.8"
serde = "1.0.189"
sha2 = "0.9"
thiserror = "1.0"
zeroize = { workspace = true }
# internal
nym-pemstore = { path = "../pemstore", version = "0.3.0" }
@@ -26,14 +28,7 @@ nym-pemstore = { path = "../pemstore", version = "0.3.0" }
[dev-dependencies]
criterion = { version = "0.3", features = ["html_reports"] }
[dependencies.ff]
version = "0.11"
default-features = false
[dependencies.group]
version = "0.11"
default-features = false
[[bench]]
name = "benchmarks"
harness = false
harness = false
@@ -264,7 +264,7 @@ fn bench_compact_ecash(c: &mut Criterion) {
.unwrap();
// SPENDING PHASE
let pay_info = PayInfo { info: [6u8; 32] };
let pay_info = PayInfo { payinfo: [6u8; 32] };
// CLIENT BENCHMARK: spend a single coin from the wallet
// group.bench_function(
// &format!(
@@ -320,7 +320,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; 32] };
let (payment2, _) = aggr_wallet
.spend(
&params,
@@ -1,8 +1,8 @@
use std::borrow::Borrow;
use bls12_381::Scalar;
use digest::Digest;
use digest::generic_array::typenum::Unsigned;
use digest::Digest;
use sha2::Sha256;
pub mod proof_spend;
@@ -12,10 +12,10 @@ type ChallengeDigest = Sha256;
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
fn compute_challenge<D, I, B>(iter: I) -> Scalar
where
D: Digest,
I: Iterator<Item=B>,
B: AsRef<[u8]>,
where
D: Digest,
I: Iterator<Item = B>,
B: AsRef<[u8]>,
{
let mut h = D::new();
for point_representation in iter {
@@ -43,8 +43,8 @@ fn produce_response(witness_replacement: &Scalar, challenge: &Scalar, secret: &S
// note: it's caller's responsibility to ensure witnesses.len() = secrets.len()
fn produce_responses<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
where
S: Borrow<Scalar>,
where
S: Borrow<Scalar>,
{
debug_assert_eq!(witnesses.len(), secrets.len());
@@ -216,16 +216,21 @@ mod tests {
.spend_verify(&params, &verification_key, &pay_info1)
.unwrap());
let pay_info2 = PayInfo::generate_payinfo(provider_keypair.public_key());
let (payment2, _) = upd_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&pay_info2,
false,
spend_vv,
).unwrap();
let pay_info2 = PayInfo::generate_payinfo(
provider_keypair.public_key().to_bytes()[..32]
.try_into()
.unwrap(),
);
let (payment2, _) = upd_wallet
.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&pay_info2,
false,
spend_vv,
)
.unwrap();
assert!(payment2
.spend_verify(&params, &verification_key, &pay_info2)
@@ -433,15 +438,21 @@ mod tests {
let current_l = aggr_wallet.l.get();
aggr_wallet.l.set(current_l - 10);
let pay_info2 = PayInfo::generate_payinfo(provider_keypair.public_key());
let (payment2, _) = aggr_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&pay_info2,
false,
spend_vv,
).unwrap();
let pay_info2 = PayInfo::generate_payinfo(
provider_keypair.public_key().to_bytes()[..32]
.try_into()
.unwrap(),
);
let (payment2, _) = aggr_wallet
.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&pay_info2,
false,
spend_vv,
)
.unwrap();
let identify_result =
identify(payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
@@ -7,7 +7,7 @@ use getset::{CopyGetters, Getters};
use crate::error::{CompactEcashError, Result};
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth, PublicKeyUser};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::traits::Bytable;
use crate::utils::{
@@ -15,8 +15,8 @@ use crate::utils::{
try_deserialize_g2_projective, try_deserialize_scalar, Signature, SignerIndex,
};
use crate::{Attribute, Base58};
use chrono::{Utc, Timelike};
use rand::{Rng, thread_rng};
use chrono::Utc;
use rand::{thread_rng, Rng};
pub mod aggregation;
pub mod identify;
+4 -10
View File
@@ -8,7 +8,9 @@ edition = "2021"
[dependencies]
#bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch = "gt-serialisation", default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] }
bls12_381 = { path = "/Users/simon/Documents/Nym/github/andrew_bls12_381", default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] }
bls12_381 = { workspace = true }
ff = { workspace = true }
group = { workspace = true }
itertools = "0.10"
digest = "0.9"
rand = "0.8"
@@ -19,14 +21,6 @@ bs58 = "0.4.0"
[dev-dependencies]
criterion = { version = "0.3", features = ["html_reports"] }
[dependencies.ff]
version = "0.11"
default-features = false
[dependencies.group]
version = "0.11"
default-features = false
[[bench]]
name = "benchmarks"
harness = false
harness = false
@@ -2,19 +2,23 @@ use std::collections::HashSet;
use std::ops::Neg;
use std::time::Duration;
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Gt, multi_miller_loop, Scalar};
use criterion::{Criterion, criterion_group, criterion_main};
use bls12_381::{
multi_miller_loop, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Gt, Scalar,
};
use criterion::{criterion_group, criterion_main, Criterion};
use ff::Field;
use group::{Curve, Group};
use itertools::izip;
use rand::seq::SliceRandom;
use rand::thread_rng;
use nym_offline_divisible_ecash::{aggregate_verification_keys, aggregate_wallets,
issue, issue_verify, PartialWallet,
PayInfo, PublicKeyUser, SecretKeyUser, ttp_keygen_authorities, ttp_keygen_users, VerificationKeyAuth, withdrawal_request};
use nym_offline_divisible_ecash::identification::{identify, IdentifyResult};
use nym_offline_divisible_ecash::setup::{GroupParameters, Parameters};
use nym_offline_divisible_ecash::{
aggregate_verification_keys, aggregate_wallets, issue, issue_verify, ttp_keygen_authorities,
ttp_keygen_users, withdrawal_request, PartialWallet, PayInfo, PublicKeyUser, SecretKeyUser,
VerificationKeyAuth,
};
#[allow(unused)]
fn double_pairing(g11: &G1Affine, g21: &G2Affine, g12: &G1Affine, g22: &G2Affine) {
@@ -118,9 +122,7 @@ fn bench_pairings(c: &mut Criterion) {
b.iter(|| exponent_in_gt(gt, r))
});
group.bench_function("single pairing", |b| {
b.iter(|| single_pairing(&g11, &g21))
});
group.bench_function("single pairing", |b| b.iter(|| single_pairing(&g11, &g21)));
group.bench_function("double pairing", |b| {
b.iter(|| double_pairing(&g11, &g21, &g12, &g22))
@@ -166,7 +168,8 @@ fn bench_divisible_ecash(c: &mut Criterion) {
// KEY GENERATION FOR THE AUTHORITIES
let threshold = (case.threshold_p * case.num_authorities as f32).round() as u64;
let authorities_keypairs = ttp_keygen_authorities(&params, threshold, case.num_authorities).unwrap();
let authorities_keypairs =
ttp_keygen_authorities(&params, threshold, case.num_authorities).unwrap();
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
.iter()
.map(|keypair| keypair.verification_key())
@@ -208,7 +211,7 @@ fn bench_divisible_ecash(c: &mut Criterion) {
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, ),
&format!("[Issuing Authority] issue_partial_wallet_with_L_{}", case.L,),
|b| {
b.iter(|| {
issue(
@@ -216,12 +219,12 @@ fn bench_divisible_ecash(c: &mut Criterion) {
&withdrawal_req,
pk_user.clone(),
&keypair.secret_key(),
).unwrap()
)
.unwrap()
})
},
);
let mut wallet_blinded_signatures = Vec::new();
for auth_keypair in authorities_keypairs {
let blind_signature = issue(
@@ -229,7 +232,8 @@ fn bench_divisible_ecash(c: &mut Criterion) {
&withdrawal_req,
pk_user.clone(),
&auth_keypair.secret_key(),
).unwrap();
)
.unwrap();
wallet_blinded_signatures.push(blind_signature);
}
@@ -237,7 +241,7 @@ fn bench_divisible_ecash(c: &mut Criterion) {
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, ),
&format!("[Client] issue_verify_a_partial_wallet_with_L_{}", case.L,),
|b| b.iter(|| issue_verify(&grp, vk, &sk_user, w, &req_info).unwrap()),
);
@@ -245,12 +249,12 @@ fn bench_divisible_ecash(c: &mut Criterion) {
wallet_blinded_signatures.iter(),
verification_keys_auth.iter()
)
.map(|(w, vk)| issue_verify(&grp, &vk, &sk_user, &w, &req_info).unwrap())
.collect();
.map(|(w, vk)| issue_verify(&grp, &vk, &sk_user, &w, &req_info).unwrap())
.collect();
// AGGREGATE WALLET
let mut wallet = aggregate_wallets(&grp, &verification_key, &sk_user, &partial_wallets).unwrap();
let mut wallet =
aggregate_wallets(&grp, &verification_key, &sk_user, &partial_wallets).unwrap();
// CLIENT BENCHMARK: aggregating all partial wallets
group.bench_function(
@@ -260,14 +264,22 @@ fn bench_divisible_ecash(c: &mut Criterion) {
),
|b| {
b.iter(|| {
aggregate_wallets(&grp, &verification_key, &sk_user, &partial_wallets)
.unwrap()
aggregate_wallets(&grp, &verification_key, &sk_user, &partial_wallets).unwrap()
})
},
);
let pay_info = PayInfo { info: [67u8; 32] };
let (payment, wallet) = wallet.spend(&params, &verification_key, &sk_user, &pay_info, case.spend_vv, false).unwrap();
let (payment, wallet) = wallet
.spend(
&params,
&verification_key,
&sk_user,
&pay_info,
case.spend_vv,
false,
)
.unwrap();
// CLIENT BENCHMARK: spend a single coin from the wallet
group.bench_function(
@@ -277,7 +289,15 @@ fn bench_divisible_ecash(c: &mut Criterion) {
),
|b| {
b.iter(|| {
wallet.spend(&params, &verification_key, &sk_user, &pay_info, case.spend_vv, true)
wallet
.spend(
&params,
&verification_key,
&sk_user,
&pay_info,
case.spend_vv,
true,
)
.unwrap()
})
},
@@ -291,7 +311,8 @@ fn bench_divisible_ecash(c: &mut Criterion) {
),
|b| {
b.iter(|| {
payment.spend_verify(&params, &verification_key, &pay_info)
payment
.spend_verify(&params, &verification_key, &pay_info)
.unwrap()
})
},
@@ -305,25 +326,50 @@ fn bench_divisible_ecash(c: &mut Criterion) {
wallet.l.set(current_l - 1);
let pay_info2 = PayInfo { info: [52u8; 32] };
let (payment2, wallet) = wallet.spend(&params, &verification_key, &sk_user, &pay_info2, 10, false).unwrap();
let (payment2, wallet) = wallet
.spend(&params, &verification_key, &sk_user, &pay_info2, 10, false)
.unwrap();
// MERCHANT BENCHMARK: identify double spending
group.bench_function(
&format!(
"[Merchant] identify_L_{}_threshold_{}_spend_vv_{}_pks_{}",
case.L, case.threshold_p, case.spend_vv, pk_all_users.len()
case.L,
case.threshold_p,
case.spend_vv,
pk_all_users.len()
),
|b| {
b.iter(|| {
identify(&params, &verification_key, &pk_all_users, payment.clone(), payment2.clone(), pay_info, pay_info2).unwrap()
identify(
&params,
&verification_key,
&pk_all_users,
payment.clone(),
payment2.clone(),
pay_info,
pay_info2,
)
.unwrap()
})
},
);
let identify_result = identify(&params, &verification_key, &pk_all_users, payment.clone(), payment2.clone(), pay_info, pay_info2).unwrap();
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(pk_user));
let identify_result = identify(
&params,
&verification_key,
&pk_all_users,
payment.clone(),
payment2.clone(),
pay_info,
pay_info2,
)
.unwrap();
assert_eq!(
identify_result,
IdentifyResult::DoubleSpendingPublicKeys(pk_user)
);
}
criterion_group!(benches, bench_divisible_ecash);
criterion_main!(benches);
criterion_main!(benches);
@@ -1,2 +1,2 @@
/// Max value of wallet
pub(crate) const L: u64 = 100;
pub(crate) const L: u64 = 100;
@@ -1,22 +1,23 @@
use bls12_381::{G1Projective, G2Prepared, G2Projective, pairing, Scalar};
use bls12_381::{pairing, G1Projective, G2Prepared, G2Projective, Scalar};
pub use scheme::aggregation::aggregate_verification_keys;
pub use scheme::aggregation::aggregate_wallets;
pub use scheme::identification;
pub use scheme::keygen::{PublicKeyUser, SecretKeyUser, VerificationKeyAuth};
pub use scheme::keygen::ttp_keygen_authorities;
pub use scheme::keygen::ttp_keygen_users;
pub use scheme::PartialWallet;
pub use scheme::PayInfo;
pub use scheme::keygen::{PublicKeyUser, SecretKeyUser, VerificationKeyAuth};
pub use scheme::setup;
pub use scheme::withdrawal::issue;
pub use scheme::withdrawal::issue_verify;
pub use scheme::withdrawal::withdrawal_request;
pub use scheme::PartialWallet;
pub use scheme::PayInfo;
pub use traits::Base58;
use crate::error::DivisibleEcashError;
use crate::traits::Bytable;
mod constants;
mod error;
mod proofs;
mod scheme;
@@ -24,6 +25,5 @@ mod scheme;
mod tests;
mod traits;
mod utils;
mod constants;
pub type Attribute = Scalar;
@@ -3,8 +3,8 @@ use std::convert::TryFrom;
use std::convert::TryInto;
use bls12_381::{G1Affine, G1Projective, Scalar};
use digest::Digest;
use digest::generic_array::typenum::Unsigned;
use digest::Digest;
use group::GroupEncoding;
use sha2::Sha256;
@@ -13,17 +13,17 @@ use crate::scheme::keygen::PublicKeyUser;
use crate::scheme::setup::GroupParameters;
use crate::utils::try_deserialize_g1_projective;
pub mod proof_withdrawal;
pub mod proof_spend;
pub mod proof_withdrawal;
type ChallengeDigest = Sha256;
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
fn compute_challenge<D, I, B>(iter: I) -> Scalar
where
D: Digest,
I: Iterator<Item=B>,
B: AsRef<[u8]>,
where
D: Digest,
I: Iterator<Item = B>,
B: AsRef<[u8]>,
{
let mut h = D::new();
for point_representation in iter {
@@ -51,8 +51,8 @@ fn produce_response(witness_replacement: &Scalar, challenge: &Scalar, secret: &S
// note: it's caller's responsibility to ensure witnesses.len() = secrets.len()
fn produce_responses<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
where
S: Borrow<Scalar>,
where
S: Borrow<Scalar>,
{
debug_assert_eq!(witnesses.len(), secrets.len());
@@ -4,12 +4,12 @@ use std::ops::Neg;
use bls12_381::{G1Projective, G2Projective, Gt, Scalar};
use group::GroupEncoding;
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::scheme::{Phi, VarPhi, Wallet};
use crate::error::{DivisibleEcashError, Result};
use crate::proofs::{compute_challenge, produce_response, produce_responses, ChallengeDigest};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::Parameters;
use crate::error::{DivisibleEcashError, Result};
use crate::utils::{try_deserialize_scalar};
use crate::scheme::{Phi, VarPhi, Wallet};
use crate::utils::try_deserialize_scalar;
pub struct SpendInstance {
pub kappa: G2Projective,
@@ -136,7 +136,8 @@ impl SpendProof {
instance: &SpendInstance,
witness: &SpendWitness,
verification_key: &VerificationKeyAuth,
vv: u64) -> Self {
vv: u64,
) -> Self {
let grp = params.get_grp();
let params_u = params.get_params_u();
let params_a = params.get_params_a();
@@ -165,20 +166,31 @@ impl SpendProof {
let zkcm_kappa = grp.gen2() * r_r
+ verification_key.alpha
+ r_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
let zkcm_phi0 = g1 * r_r1;
let zkcm_phi1 = instance.varsig_prime1 * r_v + instance.psi_g1 * r_rho1 + params_u.get_ith_eta(vv as usize) * r_r1;
let zkcm_phi1 = instance.varsig_prime1 * r_v
+ instance.psi_g1 * r_rho1
+ params_u.get_ith_eta(vv as usize) * r_r1;
let zkcm_varphi0 = g1 * r_r2;
let zkcm_varphi1 = (g1 * instance.rr) * r_sk_u + instance.theta_prime1 * r_v + instance.psi_g1 * r_rho2 + params_u.get_ith_eta(vv as usize) * r_r2;
let zkcm_pg_eq1 = instance.pg_psi0_delta * r_r_varsig1 + instance.pg_psi0_gen2 * r_r_varsig2.neg();
let zkcm_pg_eq2 = instance.pg_psi0_delta * r_r_theta1 + instance.pg_psi0_gen2 * r_r_theta2.neg();
let zkcm_pg_eq3 = instance.pg_psi0_yy * r_r_rr + instance.pg_psi0_gen2 * r_r_ss + instance.pg_psi0_ww1 * r_r_varsig2 + instance.pg_psi0_ww2 * r_r_theta2;
let zkcm_pg_eq4 = instance.pg_rr_psi1 * r_r_tt + instance.pg_psi0_tt * r_r_rr + instance.pg_psi0_psi1 * r_rho3.neg();
let zkcm_varphi1 = (g1 * instance.rr) * r_sk_u
+ instance.theta_prime1 * r_v
+ instance.psi_g1 * r_rho2
+ params_u.get_ith_eta(vv as usize) * r_r2;
let zkcm_pg_eq1 =
instance.pg_psi0_delta * r_r_varsig1 + instance.pg_psi0_gen2 * r_r_varsig2.neg();
let zkcm_pg_eq2 =
instance.pg_psi0_delta * r_r_theta1 + instance.pg_psi0_gen2 * r_r_theta2.neg();
let zkcm_pg_eq3 = instance.pg_psi0_yy * r_r_rr
+ instance.pg_psi0_gen2 * r_r_ss
+ instance.pg_psi0_ww1 * r_r_varsig2
+ instance.pg_psi0_ww2 * r_r_theta2;
let zkcm_pg_eq4 = instance.pg_rr_psi1 * r_r_tt
+ instance.pg_psi0_tt * r_r_rr
+ instance.pg_psi0_psi1 * r_rho3.neg();
let challenge = compute_challenge::<ChallengeDigest, _, _>(
std::iter::once(g1.to_bytes().as_ref())
@@ -191,7 +203,7 @@ impl SpendProof {
.chain(std::iter::once(zkcm_pg_eq1.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq2.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq3.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq4.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq4.to_compressed().as_ref())),
);
// compute response for each witness
@@ -212,7 +224,6 @@ impl SpendProof {
let response_r_rho2 = produce_response(&r_rho2, &challenge, &witness.rho2);
let response_r_rho3 = produce_response(&r_rho3, &challenge, &witness.rho3);
SpendProof {
challenge,
response_r,
@@ -251,10 +262,10 @@ impl SpendProof {
+ grp.gen2() * self.response_r
+ verification_key.alpha * (Scalar::one() - self.challenge)
+ [self.response_r_sk_u, self.response_r_v]
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
let zkcm_phi0 = g1 * self.response_r_r1 + instance.phi.0 * self.challenge;
let zkcm_phi1 = instance.varsig_prime1 * self.response_r_v
@@ -297,7 +308,7 @@ impl SpendProof {
.chain(std::iter::once(zkcm_pg_eq1.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq2.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq3.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq4.to_compressed().as_ref()))
.chain(std::iter::once(zkcm_pg_eq4.to_compressed().as_ref())),
);
challenge == self.challenge
@@ -331,7 +342,9 @@ impl TryFrom<&[u8]> for SpendProof {
let response_r_sk_u_bytes = bytes[FIELD_SIZE * 2..FIELD_SIZE * 3].try_into().unwrap();
let response_r_sk_u = try_deserialize_scalar(
&response_r_sk_u_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_sk_u".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_sk_u".to_string(),
),
)?;
let response_r_v_bytes = bytes[FIELD_SIZE * 3..FIELD_SIZE * 4].try_into().unwrap();
@@ -361,25 +374,33 @@ impl TryFrom<&[u8]> for SpendProof {
let response_r_varsig1_bytes = bytes[FIELD_SIZE * 7..FIELD_SIZE * 8].try_into().unwrap();
let response_r_varsig1 = try_deserialize_scalar(
response_r_varsig1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_varsig1".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_varsig1".to_string(),
),
)?;
let response_r_theta1_bytes = bytes[FIELD_SIZE * 8..FIELD_SIZE * 9].try_into().unwrap();
let response_r_theta1 = try_deserialize_scalar(
&response_r_theta1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_theta1".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_theta1".to_string(),
),
)?;
let response_r_varsig2_bytes = bytes[FIELD_SIZE * 9..FIELD_SIZE * 10].try_into().unwrap();
let response_r_varsig2 = try_deserialize_scalar(
&response_r_varsig2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_varsig2".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_varsig2".to_string(),
),
)?;
let response_r_theta2_bytes = bytes[FIELD_SIZE * 10..FIELD_SIZE * 11].try_into().unwrap();
let response_r_theta2 = try_deserialize_scalar(
&response_r_theta2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_theta2".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_theta2".to_string(),
),
)?;
let response_r_rr_bytes = bytes[FIELD_SIZE * 11..FIELD_SIZE * 12].try_into().unwrap();
@@ -403,19 +424,25 @@ impl TryFrom<&[u8]> for SpendProof {
let response_r_rho1_bytes = bytes[FIELD_SIZE * 14..FIELD_SIZE * 15].try_into().unwrap();
let response_r_rho1 = try_deserialize_scalar(
&response_r_rho1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho1".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_rho1".to_string(),
),
)?;
let response_r_rho2_bytes = bytes[FIELD_SIZE * 15..FIELD_SIZE * 16].try_into().unwrap();
let response_r_rho2 = try_deserialize_scalar(
&response_r_rho2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho2".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_rho2".to_string(),
),
)?;
let response_r_rho3_bytes = bytes[FIELD_SIZE * 16..FIELD_SIZE * 17].try_into().unwrap();
let response_r_rho3 = try_deserialize_scalar(
&response_r_rho3_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho3".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize response_r_rho3".to_string(),
),
)?;
Ok(SpendProof {
@@ -444,15 +471,17 @@ impl TryFrom<&[u8]> for SpendProof {
mod tests {
use std::ops::Neg;
use bls12_381::{G2Projective, pairing};
use bls12_381::{pairing, G2Projective};
use group::Curve;
use rand::thread_rng;
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::{PayInfo, Phi, VarPhi};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::keygen::{PublicKeyUser, SecretKeyUser, ttp_keygen_authorities, VerificationKeyAuth};
use crate::scheme::keygen::{
ttp_keygen_authorities, PublicKeyUser, SecretKeyUser, VerificationKeyAuth,
};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::{PayInfo, Phi, VarPhi};
use crate::utils::hash_to_scalar;
#[test]
@@ -485,18 +514,26 @@ mod tests {
let kappa = grp.gen2() * r
+ verification_key.alpha
+ attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>();
let r1 = grp.random_scalar();
let r2 = grp.random_scalar();
let phi = Phi(grp.gen1() * r1, params_u.get_ith_sigma(l as usize) * v + params_u.get_ith_eta(vv as usize) * r1);
let phi = Phi(
grp.gen1() * r1,
params_u.get_ith_sigma(l as usize) * v + params_u.get_ith_eta(vv as usize) * r1,
);
let pay_info = PayInfo { info: [78u8; 32] };
let rr = hash_to_scalar(pay_info.info);
let varphi = VarPhi(grp.gen1() * r2, (grp.gen1() * rr) * sk + params_u.get_ith_theta(l as usize) * v + params_u.get_ith_eta(vv as usize) * r2);
let varphi = VarPhi(
grp.gen1() * r2,
(grp.gen1() * rr) * sk
+ params_u.get_ith_theta(l as usize) * v
+ params_u.get_ith_eta(vv as usize) * r2,
);
// random value used to compute blinded bases
let r_varsig1 = grp.random_scalar();
@@ -507,29 +544,37 @@ mod tests {
let r_ss = grp.random_scalar();
let r_tt = grp.random_scalar();
// compute blinded bases
let psi_g1 = params_u.get_psi_g1();
let psi_g2 = params_u.get_psi_g2();
let varsig_prime1 = params_u.get_ith_sigma(l as usize) + (psi_g1 * r_varsig1);
let theta_prime1 = params_u.get_ith_theta(l as usize) + (psi_g1 * r_theta1);
let varsig_prime2 = params_u.get_ith_sigma(l as usize + vv as usize - 1) + (psi_g1 * r_varsig2);
let theta_prime2 = params_u.get_ith_theta(l as usize + vv as usize - 1) + (psi_g1 * r_theta2);
let varsig_prime2 =
params_u.get_ith_sigma(l as usize + vv as usize - 1) + (psi_g1 * r_varsig2);
let theta_prime2 =
params_u.get_ith_theta(l as usize + vv as usize - 1) + (psi_g1 * r_theta2);
let rr_prime = params_u.get_ith_sps_sign(l as usize + vv as usize - 1).rr + (psi_g1 * r_rr);
let ss_prime = params_u.get_ith_sps_sign(l as usize + vv as usize - 1).ss + (psi_g1 * r_ss);
let tt_prime = params_u.get_ith_sps_sign(l as usize + vv as usize - 1).tt + (psi_g2 * r_tt);
let rho1 = v.neg() * r_varsig1;
let rho2 = v.neg() * r_theta1;
let rho3 = r_rr * r_tt;
let pg_varsigpr1_delta = pairing(&varsig_prime1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_psi0_delta = pairing(&psi_g1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_varsigpr1_delta = pairing(
&varsig_prime1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_psi0_delta = pairing(
&psi_g1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_varsigpr2_gen2 = pairing(&varsig_prime2.to_affine(), grp.gen2());
let pg_psi0_gen2 = pairing(&psi_g1.to_affine(), grp.gen2());
let pg_thetapr1_delta = pairing(&theta_prime1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_thetapr1_delta = pairing(
&theta_prime1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_thetapr2_gen2 = pairing(&theta_prime2.to_affine(), grp.gen2());
let yy = params_u.get_sps_pk().get_yy();
let pg_rrprime_yy = pairing(&rr_prime.to_affine(), &yy.to_affine());
@@ -550,10 +595,10 @@ mod tests {
let pg_eq1 = pg_varsigpr1_delta - pg_varsigpr2_gen2;
let pg_eq2 = pg_thetapr1_delta - pg_thetapr2_gen2;
let pg_eq3 = pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 - pg_gen1_zz;
let pg_eq3 =
pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 - pg_gen1_zz;
let pg_eq4 = pg_rr_tt - pg_gen1_gen2;
let instance = SpendInstance {
kappa,
phi,
@@ -606,8 +651,5 @@ mod tests {
let zk_proof_bytes = zk_proof.to_bytes();
let zk_proof2 = SpendProof::try_from(&zk_proof_bytes[..]).unwrap();
assert_eq!(zk_proof, zk_proof2);
}
}
@@ -5,7 +5,7 @@ use group::GroupEncoding;
use itertools::izip;
use crate::error::{DivisibleEcashError, Result};
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::proofs::{compute_challenge, produce_response, produce_responses, ChallengeDigest};
use crate::scheme::keygen::PublicKeyUser;
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::try_deserialize_g1_projective;
@@ -140,10 +140,10 @@ impl WithdrawalReqProof {
// compute zkp commitments for each instance
let zkcm_com = g1 * r_com_opening
+ r_attributes
.iter()
.zip(params_u.get_gammas().iter())
.map(|(rm_i, gamma_i)| gamma_i * rm_i)
.sum::<G1Projective>();
.iter()
.zip(params_u.get_gammas().iter())
.map(|(rm_i, gamma_i)| gamma_i * rm_i)
.sum::<G1Projective>();
let zkcm_pedcom = r_pedcom_openings
.iter()
@@ -196,11 +196,7 @@ impl WithdrawalReqProof {
}
}
pub(crate) fn verify(
&self,
params: &Parameters,
instance: &WithdrawalReqInstance,
) -> bool {
pub(crate) fn verify(&self, params: &Parameters, instance: &WithdrawalReqInstance) -> bool {
let grp = params.get_grp();
let g1 = grp.gen1();
let params_u = params.get_params_u();
@@ -209,21 +205,21 @@ impl WithdrawalReqProof {
let zkcm_com = instance.com * self.challenge
+ g1 * self.response_opening
+ self
.response_attributes
.iter()
.zip(params_u.get_gammas().iter())
.map(|(m_i, gamma_i)| gamma_i * m_i)
.sum::<G1Projective>();
.response_attributes
.iter()
.zip(params_u.get_gammas().iter())
.map(|(m_i, gamma_i)| gamma_i * m_i)
.sum::<G1Projective>();
let zkcm_pedcom = izip!(
instance.pc_coms.iter(),
self.response_openings.iter(),
self.response_attributes.iter()
)
.map(|(cm_j, resp_o_j, resp_m_j)| {
cm_j * self.challenge + g1 * resp_o_j + instance.h * resp_m_j
})
.collect::<Vec<_>>();
.map(|(cm_j, resp_o_j, resp_m_j)| {
cm_j * self.challenge + g1 * resp_o_j + instance.h * resp_m_j
})
.collect::<Vec<_>>();
let zk_commitment_user_sk =
instance.pk_user.pk * self.challenge + g1 * self.response_attributes[0];
@@ -292,7 +288,6 @@ mod tests {
let grp = GroupParameters::new().unwrap();
let params = Parameters::new(grp.clone());
let sk = grp.random_scalar();
let pk_user = PublicKeyUser {
pk: grp.gen1() * sk,
@@ -304,10 +299,10 @@ mod tests {
let com_opening = grp.random_scalar();
let com = grp.gen1() * com_opening
+ attr
.iter()
.zip(params.get_params_u().get_gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
.iter()
.zip(params.get_params_u().get_gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
let h = hash_g1(com.to_bytes());
let pc_openings = grp.n_random_scalars(attr.len());
@@ -2,19 +2,19 @@ use core::iter::Sum;
use core::ops::Mul;
use std::cell::Cell;
use bls12_381::{G2Prepared, G2Projective, pairing, Scalar};
use bls12_381::{pairing, G2Prepared, G2Projective, Scalar};
use group::Curve;
use itertools::Itertools;
use crate::Attribute;
use crate::error::{DivisibleEcashError, Result};
use crate::scheme::{PartialWallet, Wallet};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::GroupParameters;
use crate::scheme::{PartialWallet, Wallet};
use crate::utils::{
check_bilinear_pairing, PartialSignature, perform_lagrangian_interpolation_at_origin,
check_bilinear_pairing, perform_lagrangian_interpolation_at_origin, PartialSignature,
Signature, SignatureShare, SignerIndex,
};
use crate::Attribute;
pub(crate) trait Aggregatable: Sized {
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
@@ -26,10 +26,10 @@ pub(crate) trait Aggregatable: Sized {
}
impl<T> Aggregatable for T
where
T: Sum,
for<'a> T: Sum<&'a T>,
for<'a> &'a T: Mul<Scalar, Output=T>,
where
T: Sum,
for<'a> T: Sum<&'a T>,
for<'a> &'a T: Mul<Scalar, Output = T>,
{
fn aggregate(aggregatable: &[T], indices: Option<&[u64]>) -> Result<T> {
if aggregatable.is_empty() {
@@ -164,4 +164,3 @@ pub fn aggregate_wallets(
l: Cell::new(1),
})
}
@@ -1,14 +1,14 @@
use std::collections::{HashMap, HashSet};
use std::ops::Neg;
use bls12_381::{Gt, pairing, Scalar};
use bls12_381::{pairing, Gt, Scalar};
use group::Curve;
use crate::error::{DivisibleEcashError, Result};
use crate::scheme::{PayInfo, Payment};
use crate::scheme::identification::IdentifyResult::DoubleSpendingPublicKeys;
use crate::scheme::keygen::{PublicKeyUser, VerificationKeyAuth};
use crate::scheme::setup::Parameters;
use crate::scheme::{PayInfo, Payment};
#[derive(Debug, Eq, PartialEq)]
pub enum IdentifyResult {
@@ -26,15 +26,23 @@ pub fn identify(
payment1: Payment,
payment2: Payment,
pay_info1: PayInfo,
pay_info2: PayInfo) -> Result<IdentifyResult> {
pay_info2: PayInfo,
) -> Result<IdentifyResult> {
let params_a = params.get_params_a();
// compute the serial numbers for k1 in [0, V1-1]
let mut serial_numbers = HashMap::new();
for k in 0..payment1.vv {
let sn = pairing(&payment1.phi.1.to_affine(), &params_a.get_ith_delta(k as usize).to_affine())
+ pairing(&payment1.phi.0.to_affine(), &params_a.get_etas_ith_jth_elem(payment1.vv as usize, k as usize).to_affine());
let sn = pairing(
&payment1.phi.1.to_affine(),
&params_a.get_ith_delta(k as usize).to_affine(),
) + pairing(
&payment1.phi.0.to_affine(),
&params_a
.get_etas_ith_jth_elem(payment1.vv as usize, k as usize)
.to_affine(),
);
serial_numbers.insert(sn, k);
}
@@ -43,8 +51,15 @@ pub fn identify(
let mut k2 = 0;
let mut duplicate_serial_numbers: Vec<(Gt, u64, u64)> = Default::default();
for j in 0..payment2.vv {
let sn = pairing(&payment2.phi.1.to_affine(), &params_a.get_ith_delta(j as usize).to_affine())
+ pairing(&payment2.phi.0.to_affine(), &params_a.get_etas_ith_jth_elem(payment2.vv as usize, j as usize).to_affine());
let sn = pairing(
&payment2.phi.1.to_affine(),
&params_a.get_ith_delta(j as usize).to_affine(),
) + pairing(
&payment2.phi.0.to_affine(),
&params_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, j);
} else {
@@ -61,13 +76,25 @@ pub fn identify(
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(), &params_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine());
+ pairing(
&payment1.varphi.0.to_affine(),
&params_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(), &params_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine());
+ pairing(
&payment2.varphi.0.to_affine(),
&params_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());
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()));
}
@@ -86,12 +113,14 @@ mod tests {
use group::Curve;
use rand::thread_rng;
use crate::scheme::{PayInfo, Payment};
use crate::scheme::aggregation::{aggregate_verification_keys, aggregate_wallets};
use crate::scheme::identification::{identify, IdentifyResult};
use crate::scheme::keygen::{PublicKeyUser, SecretKeyUser, ttp_keygen_authorities, VerificationKeyAuth};
use crate::scheme::keygen::{
ttp_keygen_authorities, PublicKeyUser, SecretKeyUser, VerificationKeyAuth,
};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::withdrawal::{issue, issue_verify, withdrawal_request};
use crate::scheme::{PayInfo, Payment};
use crate::utils::hash_g1;
#[test]
@@ -121,7 +150,6 @@ mod tests {
let sk_user2 = SecretKeyUser { sk: sk2 };
let pk_user2 = SecretKeyUser::public_key(&sk_user2, &grp);
// WITHDRAWAL REQUEST FOR USER1
let (withdrawal_req1, req_info1) = withdrawal_request(&params, &sk_user1).unwrap();
@@ -133,28 +161,52 @@ mod tests {
&withdrawal_req1,
pk_user1.clone(),
&auth_keypair.secret_key(),
).unwrap();
let partial_wallet1 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user1, &blind_signature, &req_info1).unwrap();
)
.unwrap();
let partial_wallet1 = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user1,
&blind_signature,
&req_info1,
)
.unwrap();
partial_wallets1.push(partial_wallet1);
}
// AGGREGATE WALLET FOR USER1
let mut wallet1 = aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let mut wallet1 =
aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let pay_info1 = PayInfo { info: [67u8; 32] };
let (payment1, wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false).unwrap();
let (payment1, wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false)
.unwrap();
// SPEND VERIFICATION for USER1
assert!(payment1.spend_verify(&params, &verification_key, &pay_info1).unwrap());
assert!(payment1
.spend_verify(&params, &verification_key, &pay_info1)
.unwrap());
let payment2 = payment1.clone();
// SPEND VERIFICATION for the duplicate payment
assert!(payment1.spend_verify(&params, &verification_key, &pay_info1).unwrap());
assert!(payment1
.spend_verify(&params, &verification_key, &pay_info1)
.unwrap());
let pay_info2 = pay_info1.clone();
let public_keys = HashSet::from([pk_user1, pk_user2]);
let identify_result = identify(&params, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap();
let identify_result = identify(
&params,
&verification_key,
&public_keys,
payment1,
payment2,
pay_info1,
pay_info2,
)
.unwrap();
assert_eq!(identify_result, IdentifyResult::DuplicatePayInfo(pay_info1));
}
@@ -181,7 +233,6 @@ mod tests {
let sk_user1 = SecretKeyUser { sk: sk1 };
let pk_user1 = SecretKeyUser::public_key(&sk_user1, &grp);
// GENERATE KEYS FOR OTHER USERS
let mut pk_all_users = HashSet::new();
for i in 0..50 {
@@ -203,28 +254,52 @@ mod tests {
&withdrawal_req1,
pk_user1.clone(),
&auth_keypair.secret_key(),
).unwrap();
let partial_wallet1 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user1, &blind_signature, &req_info1).unwrap();
)
.unwrap();
let partial_wallet1 = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user1,
&blind_signature,
&req_info1,
)
.unwrap();
partial_wallets1.push(partial_wallet1);
}
// AGGREGATE WALLET FOR USER1
let mut wallet1 = aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let mut wallet1 =
aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let pay_info1 = PayInfo { info: [67u8; 32] };
let (payment1, new_wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false).unwrap();
let (payment1, new_wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false)
.unwrap();
// let's reverse the spending counter in the wallet to create a double spending payment
let current_l = wallet1.l.get();
wallet1.l.set(current_l - 1);
let pay_info2 = PayInfo { info: [52u8; 32] };
let (payment2, wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info2, 10, false).unwrap();
let (payment2, wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info2, 10, false)
.unwrap();
let identify_result = identify(
&params,
&verification_key,
&pk_all_users,
payment1,
payment2,
pay_info1,
pay_info2,
)
.unwrap();
let identify_result = identify(&params, &verification_key, &pk_all_users, payment1, payment2, pay_info1, pay_info2).unwrap();
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(pk_user1));
assert_eq!(
identify_result,
IdentifyResult::DoubleSpendingPublicKeys(pk_user1)
);
}
#[test]
@@ -271,31 +346,54 @@ mod tests {
&withdrawal_req1,
pk_user1.clone(),
&auth_keypair.secret_key(),
).unwrap();
let partial_wallet1 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user1, &blind_signature, &req_info1).unwrap();
)
.unwrap();
let partial_wallet1 = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user1,
&blind_signature,
&req_info1,
)
.unwrap();
partial_wallets1.push(partial_wallet1);
}
// AGGREGATE WALLET FOR USER1
let mut wallet1 = aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let mut wallet1 =
aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let pay_info1 = PayInfo { info: [67u8; 32] };
let (payment1, new_wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false).unwrap();
let (payment1, new_wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false)
.unwrap();
// let's reverse the spending counter in the wallet to create a double spending payment
let current_l = wallet1.l.get();
wallet1.l.set(current_l - 7);
let pay_info2 = PayInfo { info: [52u8; 32] };
let (payment2, wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info2, 10, false).unwrap();
let (payment2, wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info2, 10, false)
.unwrap();
let identify_result = identify(
&params,
&verification_key,
&public_keys,
payment1,
payment2,
pay_info1,
pay_info2,
)
.unwrap();
let identify_result = identify(&params, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap();
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(pk_user1));
assert_eq!(
identify_result,
IdentifyResult::DoubleSpendingPublicKeys(pk_user1)
);
}
#[test]
fn ok_if_two_different_payments() {
let rng = thread_rng();
@@ -335,19 +433,32 @@ mod tests {
&withdrawal_req1,
pk_user1.clone(),
&auth_keypair.secret_key(),
).unwrap();
let partial_wallet1 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user1, &blind_signature, &req_info1).unwrap();
)
.unwrap();
let partial_wallet1 = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user1,
&blind_signature,
&req_info1,
)
.unwrap();
partial_wallets1.push(partial_wallet1);
}
// AGGREGATE WALLET FOR USER1
let mut wallet1 = aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let mut wallet1 =
aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap();
let pay_info1 = PayInfo { info: [67u8; 32] };
let (payment1, wallet1) = wallet1.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false).unwrap();
let (payment1, wallet1) = wallet1
.spend(&params, &verification_key, &sk_user1, &pay_info1, 10, false)
.unwrap();
// SPEND VERIFICATION for USER1
assert!(payment1.spend_verify(&params, &verification_key, &pay_info1).unwrap());
assert!(payment1
.spend_verify(&params, &verification_key, &pay_info1)
.unwrap());
// WITHDRAWAL REQUEST FOR USER2
let (withdrawal_req2, req_info2) = withdrawal_request(&params, &sk_user2).unwrap();
@@ -360,22 +471,44 @@ mod tests {
&withdrawal_req2,
pk_user2.clone(),
&auth_keypair.secret_key(),
).unwrap();
let partial_wallet2 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user2, &blind_signature, &req_info2).unwrap();
)
.unwrap();
let partial_wallet2 = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user2,
&blind_signature,
&req_info2,
)
.unwrap();
partial_wallets2.push(partial_wallet2);
}
// AGGREGATE WALLET FOR USER2
let mut wallet2 = aggregate_wallets(&grp, &verification_key, &sk_user2, &partial_wallets2).unwrap();
let mut wallet2 =
aggregate_wallets(&grp, &verification_key, &sk_user2, &partial_wallets2).unwrap();
let pay_info2 = PayInfo { info: [67u8; 32] };
let (payment2, wallet2) = wallet2.spend(&params, &verification_key, &sk_user2, &pay_info2, 10, false).unwrap();
let (payment2, wallet2) = wallet2
.spend(&params, &verification_key, &sk_user2, &pay_info2, 10, false)
.unwrap();
// SPEND VERIFICATION for USER2
assert!(payment2.spend_verify(&params, &verification_key, &pay_info2).unwrap());
assert!(payment2
.spend_verify(&params, &verification_key, &pay_info2)
.unwrap());
let public_keys = HashSet::from([pk_user1, pk_user2]);
let identify_result = identify(&params, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap();
let identify_result = identify(
&params,
&verification_key,
&public_keys,
payment1,
payment2,
pay_info1,
pay_info2,
)
.unwrap();
assert_eq!(identify_result, IdentifyResult::NotADuplicatePayment);
}
}
}
@@ -9,7 +9,10 @@ use group::Curve;
use crate::error::{DivisibleEcashError, Result};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::{Polynomial, SignerIndex, try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar, try_deserialize_scalar_vec};
use crate::utils::{
try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar,
try_deserialize_scalar_vec, Polynomial, SignerIndex,
};
#[derive(Eq, Debug, PartialEq, Clone)]
pub struct SecretKeyAuth {
@@ -236,13 +239,13 @@ impl<'a> Mul<Scalar> for &'a VerificationKeyAuth {
}
impl<T> Sum<T> for VerificationKeyAuth
where
T: Borrow<VerificationKeyAuth>,
where
T: Borrow<VerificationKeyAuth>,
{
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item=T>,
where
I: Iterator<Item = T>,
{
let mut peekable = iter.peekable();
let head_attributes = match peekable.peek() {
@@ -319,7 +322,6 @@ pub struct KeyPairUser {
public_key: PublicKeyUser,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct KeyPairAuth {
secret_key: SecretKeyAuth,
@@ -366,11 +368,11 @@ impl KeyPairUser {
}
}
pub fn ttp_keygen_authorities(
params: &Parameters,
threshold: u64,
num_authorities: u64) -> Result<Vec<KeyPairAuth>> {
num_authorities: u64,
) -> Result<Vec<KeyPairAuth>> {
if threshold == 0 {
return Err(DivisibleEcashError::Setup(
"Tried to generate threshold keys with a 0 threshold value".to_string(),
@@ -422,11 +424,15 @@ pub fn ttp_keygen_authorities(
pub fn ttp_keygen_users(params: &Parameters) -> KeyPairUser {
let grp = params.get_grp();
let sk_user = SecretKeyUser { sk: grp.random_scalar() };
let pk_user = PublicKeyUser { pk: grp.gen1() * sk_user.sk };
let sk_user = SecretKeyUser {
sk: grp.random_scalar(),
};
let pk_user = PublicKeyUser {
pk: grp.gen1() * sk_user.sk,
};
KeyPairUser {
secret_key: sk_user,
public_key: pk_user,
}
}
}
@@ -2,23 +2,26 @@ use std::cell::Cell;
use std::convert::{TryFrom, TryInto};
use std::ops::Neg;
use bls12_381::{G1Projective, G2Prepared, G2Projective, pairing, Scalar};
use bls12_381::{pairing, G1Projective, G2Prepared, G2Projective, Scalar};
use group::{Curve, GroupEncoding};
use crate::Attribute;
use crate::constants::L;
use crate::error::{DivisibleEcashError, Result};
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::{check_bilinear_pairing, hash_to_scalar, Signature, SignerIndex, try_deserialize_g1_projective, try_deserialize_scalar, try_deserialize_g2_projective};
use crate::utils::{
check_bilinear_pairing, hash_to_scalar, try_deserialize_g1_projective,
try_deserialize_g2_projective, try_deserialize_scalar, Signature, SignerIndex,
};
use crate::Attribute;
pub mod aggregation;
pub mod identification;
pub mod keygen;
pub mod setup;
pub mod structure_preserving_signature;
pub mod withdrawal;
pub mod identification;
pub fn compute_kappa(
params: &GroupParameters,
@@ -29,10 +32,10 @@ pub fn compute_kappa(
params.gen2() * blinding_factor
+ verification_key.alpha
+ attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
@@ -60,13 +63,17 @@ impl Phi {
let elem_0_bytes = bytes[0..48].try_into().unwrap();
let elem_0 = try_deserialize_g1_projective(
elem_0_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize element 0 of Phi".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize element 0 of Phi".to_string(),
),
)?;
let elem_1_bytes = bytes[48..96].try_into().unwrap();
let elem_1 = try_deserialize_g1_projective(
elem_1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize element 1 of Phi".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize element 1 of Phi".to_string(),
),
)?;
Ok(Phi(elem_0, elem_1))
@@ -98,13 +105,17 @@ impl VarPhi {
let elem_0_bytes = bytes[0..48].try_into().unwrap();
let elem_0 = try_deserialize_g1_projective(
elem_0_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize element 0 of VarPhi".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize element 0 of VarPhi".to_string(),
),
)?;
let elem_1_bytes = bytes[48..96].try_into().unwrap();
let elem_1 = try_deserialize_g1_projective(
elem_1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize element 1 of VarPhi".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize element 1 of VarPhi".to_string(),
),
)?;
Ok(VarPhi(elem_0, elem_1))
@@ -135,21 +146,49 @@ pub struct Payment {
}
impl Payment {
pub fn get_kappa(&self) -> G2Projective { self.kappa }
pub fn get_sig(&self) -> Signature { self.sig }
pub fn get_phi(&self) -> Phi { self.phi }
pub fn get_varphi(&self) -> VarPhi { self.varphi }
pub fn get_varsig_prime1(&self) -> G1Projective { self.varsig_prime1 }
pub fn get_varsig_prime2(&self) -> G1Projective { self.varsig_prime2 }
pub fn get_theta_prime1(&self) -> G1Projective { self.theta_prime1 }
pub fn get_theta_prime2(&self) -> G1Projective { self.theta_prime2 }
pub fn get_rr_prime(&self) -> G1Projective { self.rr_prime }
pub fn get_ss_prime(&self) -> G1Projective { self.ss_prime }
pub fn get_tt_prime(&self) -> G2Projective { self.tt_prime }
pub fn get_rr(&self) -> Scalar { self.rr }
pub fn get_zk_proof(&self) -> SpendProof { self.zk_proof.clone() }
pub fn get_vv(&self) -> u64 { self.vv }
pub fn to_bytes(&self) -> Vec<u8>{
pub fn get_kappa(&self) -> G2Projective {
self.kappa
}
pub fn get_sig(&self) -> Signature {
self.sig
}
pub fn get_phi(&self) -> Phi {
self.phi
}
pub fn get_varphi(&self) -> VarPhi {
self.varphi
}
pub fn get_varsig_prime1(&self) -> G1Projective {
self.varsig_prime1
}
pub fn get_varsig_prime2(&self) -> G1Projective {
self.varsig_prime2
}
pub fn get_theta_prime1(&self) -> G1Projective {
self.theta_prime1
}
pub fn get_theta_prime2(&self) -> G1Projective {
self.theta_prime2
}
pub fn get_rr_prime(&self) -> G1Projective {
self.rr_prime
}
pub fn get_ss_prime(&self) -> G1Projective {
self.ss_prime
}
pub fn get_tt_prime(&self) -> G2Projective {
self.tt_prime
}
pub fn get_rr(&self) -> Scalar {
self.rr
}
pub fn get_zk_proof(&self) -> SpendProof {
self.zk_proof.clone()
}
pub fn get_vv(&self) -> u64 {
self.vv
}
pub fn to_bytes(&self) -> Vec<u8> {
let kappa_bytes = self.kappa.to_affine().to_compressed();
let sig_bytes = self.sig.to_bytes();
let phi_bytes = self.phi.to_bytes();
@@ -189,96 +228,96 @@ impl TryFrom<&[u8]> for Payment {
type Error = DivisibleEcashError;
fn try_from(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 760 {
if bytes.len() < 760 {
return Err(DivisibleEcashError::Deserialization(
"Invalid byte array for Payment deserialization".to_string(),
));
}
let mut idx = 0;
let kappa_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
let kappa_bytes: [u8; 96] = bytes[idx..idx + 96].try_into().unwrap();
let kappa = try_deserialize_g2_projective(
&kappa_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize kappa".to_string()),
)?;
idx += 96;
let sig_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
let sig_bytes: [u8; 96] = bytes[idx..idx + 96].try_into().unwrap();
let sig = Signature::try_from(sig_bytes.as_slice())?;
idx += 96;
let phi_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
let phi_bytes: [u8; 96] = bytes[idx..idx + 96].try_into().unwrap();
let phi = Phi::from_bytes(&phi_bytes).unwrap();
idx += 96;
let varphi_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
let varphi_bytes: [u8; 96] = bytes[idx..idx + 96].try_into().unwrap();
let varphi = VarPhi::from_bytes(&varphi_bytes).unwrap();
idx += 96;
let varsig_prime1_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let varsig_prime1_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let varsig_prime1 = try_deserialize_g1_projective(
&varsig_prime1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize varsig_prime1".to_string()),
)?;
idx += 48;
let varsig_prime2_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let varsig_prime2_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let varsig_prime2 = try_deserialize_g1_projective(
&varsig_prime2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize varsig_prime2".to_string()),
)?;
idx += 48;
let theta_prime1_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let theta_prime1_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let theta_prime1 = try_deserialize_g1_projective(
&theta_prime1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize theta_prime1".to_string()),
)?;
idx += 48;
let theta_prime2_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let theta_prime2_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let theta_prime2 = try_deserialize_g1_projective(
&theta_prime2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize theta_prime2".to_string()),
)?;
idx += 48;
let rr_prime_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let rr_prime_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let rr_prime = try_deserialize_g1_projective(
&rr_prime_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize rr_prime".to_string()),
)?;
idx += 48;
let ss_prime_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
let ss_prime_bytes: [u8; 48] = bytes[idx..idx + 48].try_into().unwrap();
let ss_prime = try_deserialize_g1_projective(
&ss_prime_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize ss_prime".to_string()),
)?;
idx += 48;
let tt_prime_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
let tt_prime_bytes: [u8; 96] = bytes[idx..idx + 96].try_into().unwrap();
let tt_prime = try_deserialize_g2_projective(
&tt_prime_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize tt_prime".to_string()),
)?;
idx += 96;
let rr_bytes: [u8; 32] = bytes[idx..idx+32].try_into().unwrap();
let rr_bytes: [u8; 32] = bytes[idx..idx + 32].try_into().unwrap();
let rr = try_deserialize_scalar(
&rr_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize rr element".to_string()),
)?;
idx += 32;
let vv = u64::from_le_bytes(bytes[idx..idx+8].try_into().unwrap());
let vv = u64::from_le_bytes(bytes[idx..idx + 8].try_into().unwrap());
idx += 8;
// Deserialize the SpendProof struct
let zk_proof_bytes = &bytes[idx..];
let zk_proof = SpendProof::try_from(zk_proof_bytes)?;
Ok(Payment{
Ok(Payment {
kappa,
sig,
phi,
@@ -334,7 +373,6 @@ impl Wallet {
self.l.get()
}
pub fn spend(
&self,
params: &Parameters,
@@ -358,21 +396,24 @@ impl Wallet {
// construct kappa i.e., blinded attributes for show
let attributes = vec![sk_user.sk, self.v()];
// compute kappa
let kappa = compute_kappa(
&grp,
&verification_key,
&attributes,
sign_blinding_factor,
);
let kappa = compute_kappa(&grp, &verification_key, &attributes, sign_blinding_factor);
let r1 = grp.random_scalar();
let r2 = grp.random_scalar();
let phi = Phi(grp.gen1() * r1, params_u.get_ith_sigma(self.l() as usize) * self.v + params_u.get_ith_eta(vv as usize) * r1);
let phi = Phi(
grp.gen1() * r1,
params_u.get_ith_sigma(self.l() as usize) * self.v
+ params_u.get_ith_eta(vv as usize) * r1,
);
// compute hash of the payment info
let rr = hash_to_scalar(pay_info.info);
let varphi = VarPhi(grp.gen1() * r2, (grp.gen1() * rr) * sk_user.sk + params_u.get_ith_theta(self.l() as usize) * self.v + params_u.get_ith_eta(vv as usize) * r2);
let varphi = VarPhi(
grp.gen1() * r2,
(grp.gen1() * rr) * sk_user.sk
+ params_u.get_ith_theta(self.l() as usize) * self.v
+ params_u.get_ith_eta(vv as usize) * r2,
);
// random value used to compute blinded bases
let r_varsig1 = grp.random_scalar();
@@ -388,8 +429,10 @@ impl Wallet {
let psi_g2 = params_u.get_psi_g2();
let varsig_prime1 = params_u.get_ith_sigma(self.l() as usize) + (psi_g1 * r_varsig1);
let theta_prime1 = params_u.get_ith_theta(self.l() as usize) + (psi_g1 * r_theta1);
let varsig_prime2 = params_u.get_ith_sigma(self.l() as usize + vv as usize - 1) + (psi_g1 * r_varsig2);
let theta_prime2 = params_u.get_ith_theta(self.l() as usize + vv as usize - 1) + (psi_g1 * r_theta2);
let varsig_prime2 =
params_u.get_ith_sigma(self.l() as usize + vv as usize - 1) + (psi_g1 * r_varsig2);
let theta_prime2 =
params_u.get_ith_theta(self.l() as usize + vv as usize - 1) + (psi_g1 * r_theta2);
let tau_l_vv = params_u.get_ith_sps_sign(self.l() as usize + vv as usize - 1);
let rr_prime = tau_l_vv.rr + (psi_g1 * r_rr);
@@ -400,11 +443,20 @@ impl Wallet {
let rho2 = self.v.neg() * r_theta1;
let rho3 = r_rr * r_tt;
let pg_varsigpr1_delta = pairing(&varsig_prime1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_psi0_delta = pairing(&psi_g1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_varsigpr1_delta = pairing(
&varsig_prime1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_psi0_delta = pairing(
&psi_g1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_varsigpr2_gen2 = pairing(&varsig_prime2.to_affine(), grp.gen2());
let pg_psi0_gen2 = pairing(&psi_g1.to_affine(), grp.gen2());
let pg_thetapr1_delta = pairing(&theta_prime1.to_affine(), &params_a.get_ith_delta((vv - 1) as usize).to_affine());
let pg_thetapr1_delta = pairing(
&theta_prime1.to_affine(),
&params_a.get_ith_delta((vv - 1) as usize).to_affine(),
);
let pg_thetapr2_gen2 = pairing(&theta_prime2.to_affine(), grp.gen2());
let yy = params_u.get_sps_pk().get_yy();
let pg_rrprime_yy = pairing(&rr_prime.to_affine(), &yy.to_affine());
@@ -425,7 +477,8 @@ impl Wallet {
let pg_eq1 = pg_varsigpr1_delta - pg_varsigpr2_gen2;
let pg_eq2 = pg_thetapr1_delta - pg_thetapr2_gen2;
let pg_eq3 = pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 + pg_gen1_zz.neg();
let pg_eq3 =
pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 + pg_gen1_zz.neg();
let pg_eq4 = pg_rr_tt - pg_gen1_gen2;
let instance = SpendInstance {
@@ -511,7 +564,8 @@ impl Payment {
&self,
params: &Parameters,
verification_key: &VerificationKeyAuth,
pay_info: &PayInfo) -> Result<bool> {
pay_info: &PayInfo,
) -> Result<bool> {
if bool::from(self.sig.0.is_identity()) {
return Err(DivisibleEcashError::Spend(
"The element h of the signature equals the identity".to_string(),
@@ -549,11 +603,20 @@ impl Payment {
let psi_g1 = params_u.get_psi_g1();
let psi_g2 = params_u.get_psi_g2();
let pg_varsigpr1_delta = pairing(&self.varsig_prime1.to_affine(), &params_a.get_ith_delta((self.vv - 1) as usize).to_affine());
let pg_psi0_delta = pairing(&psi_g1.to_affine(), &params_a.get_ith_delta((self.vv - 1) as usize).to_affine());
let pg_varsigpr1_delta = pairing(
&self.varsig_prime1.to_affine(),
&params_a.get_ith_delta((self.vv - 1) as usize).to_affine(),
);
let pg_psi0_delta = pairing(
&psi_g1.to_affine(),
&params_a.get_ith_delta((self.vv - 1) as usize).to_affine(),
);
let pg_varsigpr2_gen2 = pairing(&self.varsig_prime2.to_affine(), grp.gen2());
let pg_psi0_gen2 = pairing(&psi_g1.to_affine(), grp.gen2());
let pg_thetapr1_delta = pairing(&self.theta_prime1.to_affine(), &params_a.get_ith_delta((self.vv - 1) as usize).to_affine());
let pg_thetapr1_delta = pairing(
&self.theta_prime1.to_affine(),
&params_a.get_ith_delta((self.vv - 1) as usize).to_affine(),
);
let pg_thetapr2_gen2 = pairing(&self.theta_prime2.to_affine(), grp.gen2());
let yy = params_u.get_sps_pk().get_yy();
let pg_rrprime_yy = pairing(&self.rr_prime.to_affine(), &yy.to_affine());
@@ -574,7 +637,8 @@ impl Payment {
let pg_eq1 = pg_varsigpr1_delta - pg_varsigpr2_gen2;
let pg_eq2 = pg_thetapr1_delta - pg_thetapr2_gen2;
let pg_eq3 = pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 + pg_gen1_zz.neg();
let pg_eq3 =
pg_rrprime_yy + pg_ssprime_gen2 + pg_varsigpr2_ww1 + pg_thetapr2_ww2 + pg_gen1_zz.neg();
let pg_eq4 = pg_rr_tt - pg_gen1_gen2;
let instance = SpendInstance {
@@ -603,7 +667,9 @@ impl Payment {
pg_psi0_psi1,
};
Ok(self.zk_proof.verify(&params, &instance, &verification_key, self.vv))
Ok(self
.zk_proof
.verify(&params, &instance, &verification_key, self.vv))
}
}
@@ -613,10 +679,10 @@ mod tests {
use rand::thread_rng;
use crate::scheme::{PayInfo, Phi, VarPhi, Wallet};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::keygen::{PublicKeyUser, ttp_keygen_authorities, VerificationKeyAuth};
use crate::scheme::keygen::{ttp_keygen_authorities, PublicKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::{PayInfo, Phi, VarPhi, Wallet};
use crate::utils::hash_g1;
#[test]
@@ -629,7 +695,10 @@ mod tests {
#[test]
fn varphi_to_and_from_bytes() {
let varphi = VarPhi(hash_g1("Element 0 of VarPhi"), hash_g1("Element 1 of VarPhi"));
let varphi = VarPhi(
hash_g1("Element 0 of VarPhi"),
hash_g1("Element 1 of VarPhi"),
);
let varphi_bytes = varphi.to_bytes();
let varphi_from_bytes = VarPhi::from_bytes(&varphi_bytes).unwrap();
assert_eq!(varphi, varphi_from_bytes);
@@ -657,4 +726,4 @@ mod tests {
let verification_key =
aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
}
}
}
@@ -1,7 +1,7 @@
use std::convert::TryFrom;
use std::net::ToSocketAddrs;
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, pairing, Scalar};
use bls12_381::{pairing, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar};
use ff::Field;
use group::Curve;
use rand::thread_rng;
@@ -21,7 +21,6 @@ pub struct GroupParameters {
_g2_prepared_miller: G2Prepared,
}
impl GroupParameters {
pub fn new() -> Result<GroupParameters> {
Ok(GroupParameters {
@@ -64,11 +63,17 @@ pub struct Parameters {
}
impl Parameters {
pub(crate) fn get_grp(&self) -> &GroupParameters { &self.grp }
pub(crate) fn get_grp(&self) -> &GroupParameters {
&self.grp
}
pub(crate) fn get_params_u(&self) -> &ParametersUser { &self.params_u }
pub(crate) fn get_params_u(&self) -> &ParametersUser {
&self.params_u
}
pub(crate) fn get_params_a(&self) -> &ParametersAuthority { &self.params_a }
pub(crate) fn get_params_a(&self) -> &ParametersAuthority {
&self.params_a
}
pub fn new(grp: GroupParameters) -> Parameters {
let g1 = grp.gen1();
@@ -116,10 +121,13 @@ impl Parameters {
let sps_signatures: Vec<SPSSignature> = sigmas_u
.iter()
.zip(thetas_u.iter())
.map(|(sigma, theta)| sps_keypair.sps_sk.sign(&grp, Some(&vec![*sigma, *theta]), None))
.map(|(sigma, theta)| {
sps_keypair
.sps_sk
.sign(&grp, Some(&vec![*sigma, *theta]), None)
})
.collect();
// Compute signature for each pair sigma, theta
let params_u = ParametersUser {
gammas: vec![gamma1, gamma2],
@@ -149,7 +157,9 @@ impl Parameters {
}
impl Parameters {
pub(crate) fn get_sigma(&self) -> &G1Projective { &self.tmp_sigma }
pub(crate) fn get_sigma(&self) -> &G1Projective {
&self.tmp_sigma
}
}
#[derive(Debug, Clone)]
@@ -166,31 +176,57 @@ pub struct ParametersUser {
}
impl ParametersUser {
pub(crate) fn get_gammas(&self) -> &Vec<G1Projective> { &self.gammas }
pub(crate) fn get_gammas(&self) -> &Vec<G1Projective> {
&self.gammas
}
pub(crate) fn get_psi_g1(&self) -> &G1Projective { &self.psi_g1 }
pub(crate) fn get_psi_g1(&self) -> &G1Projective {
&self.psi_g1
}
pub(crate) fn get_psi_g2(&self) -> &G2Projective { &self.psi_g2 }
pub(crate) fn get_psi_g2(&self) -> &G2Projective {
&self.psi_g2
}
pub(crate) fn get_eta(&self) -> &G1Projective { &self.eta }
pub(crate) fn get_eta(&self) -> &G1Projective {
&self.eta
}
pub(crate) fn get_etas(&self) -> &[G1Projective] { &self.etas }
pub(crate) fn get_etas(&self) -> &[G1Projective] {
&self.etas
}
pub(crate) fn get_ith_eta(&self, idx: usize) -> &G1Projective { self.etas.get(idx - 1).unwrap() }
pub(crate) fn get_ith_eta(&self, idx: usize) -> &G1Projective {
self.etas.get(idx - 1).unwrap()
}
pub(crate) fn get_sigmas(&self) -> &[G1Projective] { &self.sigmas }
pub(crate) fn get_sigmas(&self) -> &[G1Projective] {
&self.sigmas
}
pub(crate) fn get_ith_sigma(&self, idx: usize) -> &G1Projective { self.sigmas.get(idx - 1).unwrap() }
pub(crate) fn get_ith_sigma(&self, idx: usize) -> &G1Projective {
self.sigmas.get(idx - 1).unwrap()
}
pub(crate) fn get_thetas(&self) -> &[G1Projective] { &self.thetas }
pub(crate) fn get_thetas(&self) -> &[G1Projective] {
&self.thetas
}
pub(crate) fn get_ith_theta(&self, idx: usize) -> &G1Projective { self.thetas.get(idx - 1).unwrap() }
pub(crate) fn get_ith_theta(&self, idx: usize) -> &G1Projective {
self.thetas.get(idx - 1).unwrap()
}
pub(crate) fn get_sps_signs(&self) -> &[SPSSignature] { &self.sps_signatures }
pub(crate) fn get_sps_signs(&self) -> &[SPSSignature] {
&self.sps_signatures
}
pub(crate) fn get_ith_sps_sign(&self, idx: usize) -> &SPSSignature { &self.sps_signatures.get(idx - 1).unwrap() }
pub(crate) fn get_ith_sps_sign(&self, idx: usize) -> &SPSSignature {
&self.sps_signatures.get(idx - 1).unwrap()
}
pub(crate) fn get_sps_pk(&self) -> &SPSVerificationKey { &self.sps_pk }
pub(crate) fn get_sps_pk(&self) -> &SPSVerificationKey {
&self.sps_pk
}
}
#[derive(Debug, Clone)]
@@ -200,13 +236,23 @@ pub struct ParametersAuthority {
}
impl ParametersAuthority {
pub(crate) fn get_deltas(&self) -> &[G2Projective] { &self.deltas }
pub(crate) fn get_deltas(&self) -> &[G2Projective] {
&self.deltas
}
pub(crate) fn get_ith_delta(&self, idx: usize) -> &G2Projective { self.deltas.get(idx).unwrap() }
pub(crate) fn get_ith_delta(&self, idx: usize) -> &G2Projective {
self.deltas.get(idx).unwrap()
}
pub(crate) fn get_etas(&self) -> &Vec<Vec<G2Projective>> { &self.etas }
pub(crate) fn get_etas(&self) -> &Vec<Vec<G2Projective>> {
&self.etas
}
pub(crate) fn get_eta_ith_row(&self, idx: usize) -> &[G2Projective] { self.etas.get(idx).unwrap() }
pub(crate) fn get_eta_ith_row(&self, idx: usize) -> &[G2Projective] {
self.etas.get(idx).unwrap()
}
pub(crate) fn get_etas_ith_jth_elem(&self, row: usize, column: usize) -> &G2Projective { self.etas.get(row - 1).unwrap().get(column).unwrap() }
pub(crate) fn get_etas_ith_jth_elem(&self, row: usize, column: usize) -> &G2Projective {
self.etas.get(row - 1).unwrap().get(column).unwrap()
}
}
@@ -1,7 +1,7 @@
use std::fmt::Debug;
use std::ops::Neg;
use bls12_381::{G1Projective, G2Projective, Gt, pairing, Scalar};
use bls12_381::{pairing, G1Projective, G2Projective, Gt, Scalar};
use group::Curve;
use crate::scheme::setup::GroupParameters;
@@ -32,7 +32,12 @@ impl SPSSecretKey {
self.y
}
pub fn sign(&self, grp: &GroupParameters, messages_a: Option<&[G1Projective]>, messages_b: Option<&[G2Projective]>) -> SPSSignature {
pub fn sign(
&self,
grp: &GroupParameters,
messages_a: Option<&[G1Projective]>,
messages_b: Option<&[G2Projective]>,
) -> SPSSignature {
let r = grp.random_scalar();
let rr = grp.gen1() * r;
let ss: G1Projective = match messages_a {
@@ -42,9 +47,12 @@ impl SPSSecretKey {
.zip(self.ws.iter())
.map(|(m_i, w_i)| m_i * w_i.neg())
.collect();
grp.gen1() * (self.z() - r * self.y()) + prod_s.iter().fold(G1Projective::identity(), |acc, elem| acc + elem)
grp.gen1() * (self.z() - r * self.y())
+ prod_s
.iter()
.fold(G1Projective::identity(), |acc, elem| acc + elem)
}
None => grp.gen1() * (self.z() - r * self.y())
None => grp.gen1() * (self.z() - r * self.y()),
};
let tt = match messages_b {
Some(msgs_b) => {
@@ -53,26 +61,32 @@ impl SPSSecretKey {
.zip(self.us.iter())
.map(|(m_i, u_i)| m_i * u_i.neg())
.collect();
(grp.gen2() + prod_t.iter().fold(G2Projective::identity(), |acc, elem| acc + elem)) * r.invert().unwrap()
(grp.gen2()
+ prod_t
.iter()
.fold(G2Projective::identity(), |acc, elem| acc + elem))
* r.invert().unwrap()
}
None => grp.gen2() * r.invert().unwrap()
None => grp.gen2() * r.invert().unwrap(),
};
SPSSignature
{
rr,
ss,
tt,
}
SPSSignature { rr, ss, tt }
}
}
impl SPSVerificationKey {
pub fn verify(&self, grp: &GroupParameters, signature: SPSSignature, messages_a: &[G1Projective], messages_b: Option<&[G2Projective]>) -> bool {
pub fn verify(
&self,
grp: &GroupParameters,
signature: SPSSignature,
messages_a: &[G1Projective],
messages_b: Option<&[G2Projective]>,
) -> bool {
let pg_rr_yy = pairing(&signature.rr.to_affine(), &self.yy.to_affine());
let pg_ss_g2 = pairing(&signature.ss.to_affine(), grp.gen2());
let pg_g1_zz = pairing(grp.gen1(), &self.zz.to_affine());
let pg_ma_ww: Vec<Gt> = messages_a.iter()
let pg_ma_ww: Vec<Gt> = messages_a
.iter()
.zip(self.wws.iter())
.map(|(ma, ww)| pairing(&ma.to_affine(), &ww.to_affine()))
.collect();
@@ -90,7 +104,9 @@ impl SPSVerificationKey {
Some(msgs_b) => {
let pg_rr_tt = pairing(&signature.rr.to_affine(), &signature.tt.to_affine());
let pg_g1_g2 = pairing(grp.gen1(), grp.gen2());
let pg_uu_mb: Vec<Gt> = self.uus.iter()
let pg_uu_mb: Vec<Gt> = self
.uus
.iter()
.zip(msgs_b.iter())
.map(|(uu, mb)| pairing(&uu.to_affine(), &mb.to_affine()))
.collect();
@@ -110,7 +126,8 @@ impl SPSVerificationKey {
None => {
let pg_sign_rr_yy = pairing(&signature.rr.to_affine(), &self.yy.to_affine());
let pg_sign_ss_gen2 = pairing(&signature.ss.to_affine(), &grp.gen2());
let pg_ma_wws: Vec<Gt> = messages_a.iter()
let pg_ma_wws: Vec<Gt> = messages_a
.iter()
.zip(self.wws.iter())
.map(|(ma, ww)| pairing(&ma.to_affine(), &ww.to_affine()))
.collect();
@@ -128,7 +145,9 @@ impl SPSVerificationKey {
assert_eq!(pg_sign_rr_yy + pg_sign_ss_gen2 + prod_pg_ma_wws, pg_gen1_zz);
assert_eq!(pg_rr_tt, pg_gen1_gen2);
if pg_sign_rr_yy + pg_sign_ss_gen2 + prod_pg_ma_wws == pg_gen1_zz && pg_rr_tt == pg_gen1_gen2 {
if pg_sign_rr_yy + pg_sign_ss_gen2 + prod_pg_ma_wws == pg_gen1_zz
&& pg_rr_tt == pg_gen1_gen2
{
true
} else {
false
@@ -139,11 +158,17 @@ impl SPSVerificationKey {
return result;
}
pub fn get_ith_ww(&self, idx: usize) -> &G2Projective { return self.wws.get(idx).unwrap(); }
pub fn get_ith_ww(&self, idx: usize) -> &G2Projective {
return self.wws.get(idx).unwrap();
}
pub fn get_zz(&self) -> &G2Projective { return &self.zz; }
pub fn get_zz(&self) -> &G2Projective {
return &self.zz;
}
pub fn get_yy(&self) -> &G2Projective { return &self.yy; }
pub fn get_yy(&self) -> &G2Projective {
return &self.yy;
}
}
pub struct SPSKeyPair {
@@ -187,7 +212,6 @@ pub struct SPSSignature {
pub tt: G2Projective,
}
#[cfg(test)]
mod tests {
use rand::thread_rng;
@@ -204,7 +228,9 @@ mod tests {
let msgs_a = vec![hash_g1("messageA1"), hash_g1("messageA2")];
let msgs_b = vec![hash_g2("messageB1"), hash_g2("messageB2")];
let signature = sps_keypair.sps_sk.sign(&grp, Some(&msgs_a), Some(&msgs_b));
assert!(sps_keypair.sps_vk.verify(&grp, signature, &msgs_a, Some(&msgs_b)));
assert!(sps_keypair
.sps_vk
.verify(&grp, signature, &msgs_a, Some(&msgs_b)));
}
#[test]
@@ -216,4 +242,4 @@ mod tests {
let signature = sps_keypair.sps_sk.sign(&grp, Some(&msgs_a), None);
assert!(sps_keypair.sps_vk.verify(&grp, signature, &msgs_a, None));
}
}
}
@@ -2,11 +2,13 @@ use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
use group::{Curve, GroupEncoding};
use crate::error::{DivisibleEcashError, Result};
use crate::proofs::proof_withdrawal::{WithdrawalReqInstance, WithdrawalReqProof, WithdrawalReqWitness};
use crate::proofs::proof_withdrawal::{
WithdrawalReqInstance, WithdrawalReqProof, WithdrawalReqWitness,
};
use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser, VerificationKeyAuth};
use crate::scheme::PartialWallet;
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::{BlindedSignature, check_bilinear_pairing, hash_g1, Signature};
use crate::scheme::PartialWallet;
use crate::utils::{check_bilinear_pairing, hash_g1, BlindedSignature, Signature};
pub struct WithdrawalRequest {
com_hash: G1Projective,
@@ -21,7 +23,10 @@ pub struct RequestInfo {
v: Scalar,
}
pub fn withdrawal_request(params: &Parameters, sk_user: &SecretKeyUser) -> Result<(WithdrawalRequest, RequestInfo)> {
pub fn withdrawal_request(
params: &Parameters,
sk_user: &SecretKeyUser,
) -> Result<(WithdrawalRequest, RequestInfo)> {
let grp = params.get_grp();
let g1 = grp.gen1();
let params_u = params.get_params_u();
@@ -30,10 +35,10 @@ pub fn withdrawal_request(params: &Parameters, sk_user: &SecretKeyUser) -> Resul
let com_opening = grp.random_scalar();
let commitment = g1 * com_opening
+ attributes
.iter()
.zip(params_u.get_gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
.iter()
.zip(params_u.get_gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
// Value h in the paper
let com_hash = hash_g1(commitment.to_bytes());
@@ -45,7 +50,6 @@ pub fn withdrawal_request(params: &Parameters, sk_user: &SecretKeyUser) -> Resul
.map(|(o_j, m_j)| g1 * o_j + com_hash * m_j)
.collect::<Vec<_>>();
// construct a zk proof of knowledge proving possession of m1, m2, o, o1, o2
let instance = WithdrawalReqInstance {
com: commitment,
@@ -78,7 +82,12 @@ pub fn withdrawal_request(params: &Parameters, sk_user: &SecretKeyUser) -> Resul
Ok((req, req_info))
}
pub fn issue(params: &Parameters, req: &WithdrawalRequest, pk_u: PublicKeyUser, sk_a: &SecretKeyAuth) -> Result<BlindedSignature> {
pub fn issue(
params: &Parameters,
req: &WithdrawalRequest,
pk_u: PublicKeyUser,
sk_a: &SecretKeyAuth,
) -> Result<BlindedSignature> {
let h = hash_g1(req.com.to_bytes());
if !(h == req.com_hash) {
return Err(DivisibleEcashError::WithdrawalRequestVerification(
@@ -115,8 +124,8 @@ pub fn issue_verify(
vk_auth: &VerificationKeyAuth,
sk_user: &SecretKeyUser,
blind_signature: &BlindedSignature,
req_info: &RequestInfo) -> Result<PartialWallet> {
req_info: &RequestInfo,
) -> Result<PartialWallet> {
// Parse the blinded signature
let h = blind_signature.0;
let c = blind_signature.1;
@@ -163,4 +172,4 @@ pub fn issue_verify(
v: req_info.v,
idx: None,
})
}
}
@@ -1,12 +1,16 @@
use rand::thread_rng;
use crate::error::DivisibleEcashError;
use crate::scheme::{PayInfo, Payment};
use crate::scheme::aggregation::{aggregate_signatures, aggregate_verification_keys, aggregate_wallets};
use crate::scheme::aggregation::{
aggregate_signatures, aggregate_verification_keys, aggregate_wallets,
};
use crate::scheme::identification::identify;
use crate::scheme::keygen::{PublicKeyUser, SecretKeyUser, ttp_keygen_authorities, VerificationKeyAuth};
use crate::scheme::keygen::{
ttp_keygen_authorities, PublicKeyUser, SecretKeyUser, VerificationKeyAuth,
};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::withdrawal::{issue, issue_verify, withdrawal_request};
use crate::scheme::{PayInfo, Payment};
#[test]
// Test wa full end to end flow of withdrawal request, issuance,
@@ -43,7 +47,13 @@ fn main() -> Result<(), DivisibleEcashError> {
pk_user.clone(),
&auth_keypair.secret_key(),
)?;
let partial_wallet = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user, &blind_signature, &req_info)?;
let partial_wallet = issue_verify(
&grp,
&auth_keypair.verification_key(),
&sk_user,
&blind_signature,
&req_info,
)?;
partial_wallets.push(partial_wallet);
}
@@ -51,10 +61,13 @@ fn main() -> Result<(), DivisibleEcashError> {
let mut wallet = aggregate_wallets(&grp, &verification_key, &sk_user, &partial_wallets)?;
let pay_info = PayInfo { info: [67u8; 32] };
let (payment, wallet) = wallet.spend(&params, &verification_key, &sk_user, &pay_info, 10, false)?;
let (payment, wallet) =
wallet.spend(&params, &verification_key, &sk_user, &pay_info, 10, false)?;
// SPEND VERIFICATION
assert!(payment.spend_verify(&params, &verification_key, &pay_info).unwrap());
// SPEND VERIFICATION
assert!(payment
.spend_verify(&params, &verification_key, &pay_info)
.unwrap());
let payment_bytes = payment.to_bytes();
let payment2 = Payment::try_from(&payment_bytes[..]).unwrap();
assert_eq!(payment, payment2);
@@ -6,10 +6,10 @@ use core::ops::Mul;
use std::convert::{TryFrom, TryInto};
use std::ops::Neg;
use bls12_381::{
G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, multi_miller_loop, Scalar,
};
use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve, HashToField};
use bls12_381::{
multi_miller_loop, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar,
};
use ff::Field;
use group::{Curve, Group};
@@ -85,9 +85,9 @@ pub(crate) fn perform_lagrangian_interpolation_at_origin<T>(
points: &[SignerIndex],
values: &[T],
) -> Result<T>
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output=T>,
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output = T>,
{
if points.is_empty() || values.is_empty() {
return Err(DivisibleEcashError::Interpolation(
+8 -15
View File
@@ -9,22 +9,15 @@ 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"] }
itertools = "0.10"
digest = "0.9"
rand = "0.8"
thiserror = "1.0"
sha2 = "0.9"
bls12_381 = { workspace = true }
bs58 = "0.4.0"
digest = "0.9"
ff = { workspace = true }
group = { workspace = true }
itertools = "0.10"
rand = "0.8"
sha2 = "0.9"
thiserror = "1.0"
[dev-dependencies]
criterion = { version = "0.3", features = ["html_reports"] }
[dependencies.ff]
version = "0.10"
default-features = false
[dependencies.group]
version = "0.10"
default-features = false
@@ -0,0 +1 @@
@@ -1,4 +1,3 @@
mod error;
mod scheme;
mod traits;
mod utils;
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+8 -14
View File
@@ -15,16 +15,10 @@ use rand::seq::SliceRandom;
use std::ops::Neg;
use std::time::Duration;
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, multi_miller_loop, Scalar};
use criterion::{Criterion, criterion_group, criterion_main};
use ff::Field;
use group::{Curve, Group};
use rand::seq::SliceRandom;
use nymcoconut::{
aggregate_signature_shares, aggregate_verification_keys, Attribute, blind_sign,
BlindedSignature, elgamal_keygen, Parameters, prepare_blind_sign, prove_bandwidth_credential,
setup, Signature, SignatureShare, ttp_keygen, VerificationKey, verify_credential,
aggregate_signature_shares, aggregate_verification_keys, blind_sign, elgamal_keygen,
prepare_blind_sign, prove_bandwidth_credential, setup, ttp_keygen, verify_credential,
Attribute, BlindedSignature, Parameters, Signature, SignatureShare, VerificationKey,
};
#[allow(unused)]
@@ -151,7 +145,7 @@ fn unblind_and_aggregate(
&attributes,
&unblinded_signature_shares,
)
.unwrap()
.unwrap()
}
struct BenchCase {
@@ -229,7 +223,7 @@ fn bench_coconut(c: &mut Criterion) {
&blind_sign_request,
&public_attributes,
)
.unwrap()
.unwrap()
})
},
);
@@ -244,7 +238,7 @@ fn bench_coconut(c: &mut Criterion) {
&blind_sign_request,
&public_attributes,
)
.unwrap();
.unwrap();
blinded_signatures.push(blinded_signature)
}
@@ -325,7 +319,7 @@ fn bench_coconut(c: &mut Criterion) {
serial_number,
binding_number,
)
.unwrap();
.unwrap();
// CLIENT BENCHMARK
group.bench_function(
@@ -344,7 +338,7 @@ fn bench_coconut(c: &mut Criterion) {
serial_number,
binding_number,
)
.unwrap()
.unwrap()
})
},
);
+2
View File
@@ -123,6 +123,7 @@ impl From<ConfigV1_1_31> for Config {
nym_api_urls: value.gateway.nym_api_urls,
nyxd_urls: value.gateway.nyxd_urls,
cosmos_mnemonic: value.gateway.cosmos_mnemonic,
offline_credential_verification: false,
},
wireguard: nym_node::config::Wireguard {
enabled: value.wireguard.enabled,
@@ -216,6 +217,7 @@ pub struct GatewayV1_1_31 {
// #[deprecated(note = "move to storage")]
// TODO: I don't think this should be stored directly in the config...
pub cosmos_mnemonic: bip39::Mnemonic,
pub offline_credential_verification: bool,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
@@ -201,12 +201,6 @@ impl EcashVerifier {
api_clients: Vec<CoconutApiClient>,
credential: EcashCredential,
) -> Result<(), RequestHandlingError> {
let req = nym_api_requests::coconut::VerifyCredentialBody::new(
credential.clone(),
proposal_id,
self.nyxd_client.address(),
);
for client in api_clients {
self.cred_sender
.unbounded_send(PendingCredential {
+5 -5
View File
@@ -467,14 +467,14 @@ impl<St> Gateway<St> {
let ecash_verifier = {
let nyxd_client = self.random_nyxd_client()?;
let ecash_params = self.get_ecash_parameters().await?;
EcashVerifier::new(
Arc::new(EcashVerifier::new(
nyxd_client,
ecash_params,
self.identity_keypair.public_key().to_bytes(),
shutdown.subscribe().named("EcashVerifier"),
self.storage.clone(),
self.config.gateway.offline_credential_verification,
)
))
};
let mix_forwarding_channel =
@@ -504,7 +504,7 @@ impl<St> Gateway<St> {
mix_forwarding_channel.clone(),
active_clients_store.clone(),
shutdown.subscribe().named("websocket::Listener"),
Arc::new(coconut_verifier),
Arc::clone(&ecash_verifier),
);
let nr_request_filter = if self.config.network_requester.enabled {
@@ -527,7 +527,7 @@ impl<St> Gateway<St> {
if self.config.ip_packet_router.enabled {
let embedded_ip_sp = self
.start_ip_packet_router(
mix_forwarding_channel,
mix_forwarding_channel.clone(),
shutdown.subscribe().named("ip_service_provider"),
)
.await?;
@@ -548,7 +548,7 @@ impl<St> Gateway<St> {
mix_forwarding_channel,
active_clients_store,
shutdown.subscribe().named("websocket::Listener"),
Arc::new(ecash_verifier),
Arc::clone(&ecash_verifier),
);
// Once this is a bit more mature, make this a commandline flag instead of a compile time
+3 -3
View File
@@ -6,11 +6,11 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub(crate) enum StorageError {
#[error("Database experienced an internal error: {0}")]
InternalDatabaseError(#[from] sqlx::Error),
InternalDatabase(#[from] sqlx::Error),
#[error("Failed to perform database migration: {0}")]
MigrationError(#[from] sqlx::migrate::MigrateError),
Migration(#[from] sqlx::migrate::MigrateError),
#[error("Somehow stored data is incorrect: {0}")]
DataCorruptionError(String),
DataCorruption(String),
}
+4 -5
View File
@@ -384,17 +384,16 @@ impl Storage for PersistentStorage {
.into_iter()
.map(|stored_pending| {
let credential = EcashCredential::try_from_bs58(stored_pending.credential)
.map_err(|err| StorageError::DataCorruptionError(err.to_string()))?;
.map_err(|err| StorageError::DataCorruption(err.to_string()))?;
Ok((
stored_pending.id,
PendingCredential {
credential,
address: AccountId::from_str(&stored_pending.address)
.map_err(|err| StorageError::DataCorruptionError(err.to_string()))?,
.map_err(|err| StorageError::DataCorruption(err.to_string()))?,
client: NymApiClient::new(
Url::from_str(&stored_pending.api_url).map_err(|err| {
StorageError::DataCorruptionError(err.to_string())
})?,
Url::from_str(&stored_pending.api_url)
.map_err(|err| StorageError::DataCorruption(err.to_string()))?,
),
},
))