add params in ecashcredential
This commit is contained in:
Generated
+32
-7
@@ -6065,6 +6065,7 @@ dependencies = [
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
"nym-credential-storage",
|
||||
@@ -6086,7 +6087,6 @@ dependencies = [
|
||||
"nym-topology",
|
||||
"nym-validator-client",
|
||||
"nym-vesting-contract-common",
|
||||
"nym_compact_ecash",
|
||||
"okapi",
|
||||
"pin-project",
|
||||
"rand 0.7.3",
|
||||
@@ -6121,12 +6121,16 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"getset",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-mixnet-contract-common",
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
"nym-node-requests",
|
||||
=======
|
||||
"nym_compact_ecash",
|
||||
>>>>>>> d6ab65512 (issuance cli side)
|
||||
=======
|
||||
>>>>>>> 0d6e14066 (change crate name from _ to -)
|
||||
"schemars",
|
||||
"serde",
|
||||
"ts-rs",
|
||||
@@ -6138,12 +6142,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-credential-storage",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-network-defaults",
|
||||
"nym-validator-client",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"thiserror",
|
||||
"url",
|
||||
@@ -6433,6 +6437,24 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-compact-ecash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bls12_381 0.6.0",
|
||||
"bs58 0.4.0",
|
||||
"criterion 0.3.6",
|
||||
"digest 0.9.0",
|
||||
"ff 0.11.1",
|
||||
"getset",
|
||||
"group 0.11.0",
|
||||
"itertools 0.10.5",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"sha2 0.9.9",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-config"
|
||||
version = "0.1.0"
|
||||
@@ -6494,9 +6516,9 @@ dependencies = [
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-crypto",
|
||||
"nym-validator-client",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"thiserror",
|
||||
]
|
||||
@@ -6648,6 +6670,7 @@ dependencies = [
|
||||
"nym-api-requests",
|
||||
"nym-bin-common",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
@@ -6665,7 +6688,6 @@ dependencies = [
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
"nym-wireguard",
|
||||
"nym_compact_ecash",
|
||||
"once_cell",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
@@ -6694,6 +6716,7 @@ dependencies = [
|
||||
"log",
|
||||
"nym-bandwidth-controller",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-credential-storage",
|
||||
"nym-crypto",
|
||||
"nym-gateway-requests",
|
||||
@@ -6702,7 +6725,6 @@ dependencies = [
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"thiserror",
|
||||
@@ -6726,11 +6748,11 @@ dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
"log",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -7651,6 +7673,7 @@ dependencies = [
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
"nym-coconut-interface",
|
||||
"nym-compact-ecash",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
"nym-ephemera-common",
|
||||
@@ -7661,7 +7684,6 @@ dependencies = [
|
||||
"nym-network-defaults",
|
||||
"nym-service-provider-directory-common",
|
||||
"nym-vesting-contract-common",
|
||||
"nym_compact_ecash",
|
||||
"openssl",
|
||||
"prost 0.12.1",
|
||||
"reqwest",
|
||||
@@ -7744,6 +7766,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
<<<<<<< HEAD
|
||||
name = "nym_compact_ecash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
@@ -7789,6 +7812,8 @@ dependencies = [
|
||||
<<<<<<< HEAD
|
||||
name = "nymvisor"
|
||||
=======
|
||||
=======
|
||||
>>>>>>> 0d6e14066 (change crate name from _ to -)
|
||||
name = "nym_offline_divisible_ecash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
|
||||
@@ -12,7 +12,7 @@ thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
||||
nym-coconut-interface = { path = "../coconut-interface" }
|
||||
nym_compact_ecash = { path = "../nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../nym_offline_compact_ecash" }
|
||||
nym-credential-storage = { path = "../credential-storage" }
|
||||
nym-credentials = { path = "../credentials" }
|
||||
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
|
||||
|
||||
@@ -9,7 +9,7 @@ use nym_credentials::coconut::bandwidth::BandwidthVoucher;
|
||||
use nym_credentials::coconut::utils::obtain_aggregate_signature;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_network_defaults::ECASH_INFO;
|
||||
use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||
use nym_validator_client::nyxd::contract_traits::CoconutBandwidthSigningClient;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
@@ -74,15 +74,11 @@ where
|
||||
.await?
|
||||
.ok_or(BandwidthControllerError::NoThreshold)?;
|
||||
|
||||
let coconut_api_clients = all_coconut_api_clients(client, epoch_id).await?;
|
||||
let ecash_api_clients = all_ecash_api_clients(client, epoch_id).await?;
|
||||
|
||||
let wallet = obtain_aggregate_signature(
|
||||
&state.params,
|
||||
&state.voucher,
|
||||
&coconut_api_clients,
|
||||
threshold,
|
||||
)
|
||||
.await?;
|
||||
let wallet =
|
||||
obtain_aggregate_signature(&state.params, &state.voucher, &ecash_api_clients, threshold)
|
||||
.await?;
|
||||
storage
|
||||
.insert_ecash_credential(
|
||||
ECASH_INFO.to_string(),
|
||||
|
||||
@@ -8,7 +8,7 @@ use nym_compact_ecash::{Base58, PayInfo, SecretKeyUser};
|
||||
use nym_credential_storage::error::StorageError;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::obtain_aggregate_verification_key;
|
||||
use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -46,9 +46,9 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
let epoch_id = u64::from_str(&ecash_credential.epoch_id)
|
||||
.map_err(|_| StorageError::InconsistentData)?;
|
||||
|
||||
let coconut_api_clients = all_coconut_api_clients(&self.client, epoch_id).await?;
|
||||
let ecash_api_clients = all_ecash_api_clients(&self.client, epoch_id).await?;
|
||||
|
||||
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
|
||||
let verification_key = obtain_aggregate_verification_key(&ecash_api_clients).await?;
|
||||
|
||||
let some_l_i_guess = 100; //SW: TEMPORARY VALUE
|
||||
let params = setup(some_l_i_guess);
|
||||
@@ -67,7 +67,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
nb_tickets,
|
||||
)?;
|
||||
|
||||
let credential = EcashCredential::new(payment, pay_info, epoch_id);
|
||||
let credential = EcashCredential::new(params, payment, pay_info, epoch_id);
|
||||
|
||||
Ok((credential, wallet.to_bs58(), ecash_credential.id))
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ tokio = { version = "1.24.1", features = ["macros"] }
|
||||
# internal
|
||||
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
|
||||
nym-coconut-interface = { path = "../../coconut-interface" }
|
||||
nym_compact_ecash = { path = "../../nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../../nym_offline_compact_ecash" }
|
||||
nym-credential-storage = { path = "../../credential-storage" }
|
||||
nym-crypto = { path = "../../crypto" }
|
||||
nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
|
||||
|
||||
@@ -33,7 +33,7 @@ futures = { workspace = true }
|
||||
openssl = { version = "^0.10.55", features = ["vendored"], optional = true }
|
||||
|
||||
nym-coconut-interface = { path = "../../coconut-interface" }
|
||||
nym_compact_ecash = { path = "../../nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../../nym_offline_compact_ecash" }
|
||||
nym-network-defaults = { path = "../../network-defaults" }
|
||||
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ impl TryFrom<ContractVKShare> for CoconutApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn all_coconut_api_clients<C>(
|
||||
pub async fn all_ecash_api_clients<C>(
|
||||
client: &C,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<Vec<CoconutApiClient>, CoconutApiError>
|
||||
|
||||
@@ -13,7 +13,7 @@ log = { workspace = true }
|
||||
|
||||
# I guess temporarily until we get serde support in coconut up and running
|
||||
nym-coconut-interface = { path = "../coconut-interface" }
|
||||
nym_compact_ecash = { path = "../nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../nym_offline_compact_ecash" }
|
||||
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "hashing"] }
|
||||
nym-api-requests = { path = "../../nym-api/nym-api-requests" }
|
||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "nym_compact_ecash"
|
||||
name = "nym-compact-ecash"
|
||||
version = "0.1.0"
|
||||
authors = ["Ania Piotrowska <ania@nymtech.net>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -4,20 +4,22 @@
|
||||
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 nym_compact_ecash::{
|
||||
aggregate_verification_keys, aggregate_wallets, generate_keypair_user,
|
||||
issue_verify, issue_wallet, PartialWallet,
|
||||
PayInfo, PublicKeyUser, SecretKeyUser, ttp_keygen, VerificationKeyAuth, withdrawal_request,
|
||||
};
|
||||
use nym_compact_ecash::identify::{identify, IdentifyResult};
|
||||
use nym_compact_ecash::setup::setup;
|
||||
use nym_compact_ecash::{
|
||||
aggregate_verification_keys, aggregate_wallets, generate_keypair_user, issue_verify,
|
||||
issue_wallet, ttp_keygen, withdrawal_request, PartialWallet, PayInfo, PublicKeyUser,
|
||||
SecretKeyUser, VerificationKeyAuth,
|
||||
};
|
||||
|
||||
#[allow(unused)]
|
||||
fn double_pairing(g11: &G1Affine, g21: &G2Affine, g12: &G1Affine, g22: &G2Affine) {
|
||||
@@ -121,9 +123,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))
|
||||
@@ -230,8 +230,8 @@ fn bench_compact_ecash(c: &mut Criterion) {
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
.map(|(w, vk)| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
|
||||
// CLIENT BENCHMARK: aggregating all partial wallets
|
||||
// group.bench_function(
|
||||
@@ -261,7 +261,7 @@ fn bench_compact_ecash(c: &mut Criterion) {
|
||||
&unblinded_wallet_shares,
|
||||
&req_info,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
// SPENDING PHASE
|
||||
let pay_info = PayInfo { info: [6u8; 32] };
|
||||
@@ -321,14 +321,16 @@ fn bench_compact_ecash(c: &mut Criterion) {
|
||||
aggr_wallet.l.set(current_l - case.spend_vv);
|
||||
|
||||
let pay_info2 = PayInfo { info: [7u8; 32] };
|
||||
let (payment2, _) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
true,
|
||||
case.spend_vv,
|
||||
).unwrap();
|
||||
let (payment2, _) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
true,
|
||||
case.spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// GENERATE KEYS FOR OTHER USERS
|
||||
let mut public_keys: Vec<PublicKeyUser> = Default::default();
|
||||
@@ -344,16 +346,28 @@ fn bench_compact_ecash(c: &mut Criterion) {
|
||||
group.bench_function(
|
||||
&format!(
|
||||
"[Merchant] identify_L_{}_threshold_{}_spend_vv_{}_pks_{}",
|
||||
case.L, case.threshold_p, case.spend_vv, public_keys.len()
|
||||
case.L,
|
||||
case.threshold_p,
|
||||
case.spend_vv,
|
||||
public_keys.len()
|
||||
),
|
||||
|b| {
|
||||
b.iter(|| {
|
||||
identify(¶ms, &verification_key, payment.clone(), payment2.clone(), pay_info.clone(), pay_info2.clone()).unwrap()
|
||||
identify(
|
||||
payment.clone(),
|
||||
payment2.clone(),
|
||||
pay_info.clone(),
|
||||
pay_info2.clone(),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
},
|
||||
);
|
||||
let identify_result = identify(¶ms, &verification_key, payment, payment2, pay_info.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key()));
|
||||
let identify_result = identify(payment, payment2, pay_info.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(
|
||||
identify_result,
|
||||
IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key())
|
||||
);
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_compact_ecash);
|
||||
|
||||
@@ -41,7 +41,7 @@ pub enum CompactEcashError {
|
||||
)]
|
||||
DeserializationMinLength { min: usize, actual: usize },
|
||||
|
||||
#[error("Tried to deserialize {object} with bytes of invalid length. Expected {actual} < {} or {modulus_target} % {modulus} == 0")]
|
||||
#[error("Tried to deserialize {object} with bytes of invalid length. Expected {actual} < {target} or {modulus_target} % {modulus} == 0")]
|
||||
DeserializationInvalidLength {
|
||||
actual: usize,
|
||||
target: usize,
|
||||
|
||||
@@ -4,10 +4,13 @@ use bls12_381::{G1Projective, G2Projective, Scalar};
|
||||
use group::{Curve, GroupEncoding};
|
||||
|
||||
use crate::error::{CompactEcashError, 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::VerificationKeyAuth;
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar_vec, try_deserialize_scalar};
|
||||
use crate::utils::{
|
||||
try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar,
|
||||
try_deserialize_scalar_vec,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
@@ -66,8 +69,7 @@ impl TryFrom<&[u8]> for SpendInstance {
|
||||
|
||||
aa.push(aa_elem)
|
||||
}
|
||||
j += j + a_len as usize * 48;
|
||||
|
||||
j += a_len as usize * 48;
|
||||
|
||||
let cc_bytes = bytes[j..j + 48].try_into().unwrap();
|
||||
let cc = try_deserialize_g1_projective(
|
||||
@@ -100,7 +102,7 @@ impl TryFrom<&[u8]> for SpendInstance {
|
||||
|
||||
ss.push(ss_elem)
|
||||
}
|
||||
j += j + s_len as usize * 48;
|
||||
j += s_len as usize * 48;
|
||||
|
||||
let t_len = u64::from_le_bytes(bytes[j..j + 8].try_into().unwrap());
|
||||
j += 8;
|
||||
@@ -126,8 +128,7 @@ impl TryFrom<&[u8]> for SpendInstance {
|
||||
|
||||
tt.push(tt_elem)
|
||||
}
|
||||
j += j + t_len as usize * 48;
|
||||
|
||||
j += t_len as usize * 48;
|
||||
|
||||
let kappa_k_len = u64::from_le_bytes(bytes[j..j + 8].try_into().unwrap());
|
||||
j += 8;
|
||||
@@ -254,45 +255,44 @@ impl SpendProof {
|
||||
let zkcm_kappa = grparams.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_cc = g1 * r_o_c + gamma1 * r_v;
|
||||
|
||||
let zkcm_aa: Vec<G1Projective> =
|
||||
r_o_a
|
||||
.iter()
|
||||
.zip(r_lk.iter()).map(|(r_o_a_k, r_l_k)| g1 * r_o_a_k + gamma1 * r_l_k)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_aa_bytes = zkcm_aa
|
||||
let zkcm_aa: Vec<G1Projective> = r_o_a
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.zip(r_lk.iter())
|
||||
.map(|(r_o_a_k, r_l_k)| g1 * r_o_a_k + gamma1 * r_l_k)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_ss = r_mu.iter().map(|r_mu_k| grparams.delta() * r_mu_k).collect::<Vec<_>>();
|
||||
let zkcm_aa_bytes = zkcm_aa.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_ss_bytes = zkcm_ss
|
||||
let zkcm_ss = r_mu
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.map(|r_mu_k| grparams.delta() * r_mu_k)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_ss_bytes = zkcm_ss.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_tt = rr
|
||||
.iter()
|
||||
.zip(r_mu.iter()).map(|(rr_k, r_mu_k)| g1 * r_sk + (g1 * rr_k) * r_mu_k).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_tt_bytes = zkcm_tt
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.zip(r_mu.iter())
|
||||
.map(|(rr_k, r_mu_k)| g1 * r_sk + (g1 * rr_k) * r_mu_k)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_gamma11 = instance.aa
|
||||
let zkcm_tt_bytes = zkcm_tt.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_gamma11 = instance
|
||||
.aa
|
||||
.iter()
|
||||
.zip(r_mu.iter())
|
||||
.zip(r_o_mu.iter())
|
||||
.map(|((aa_k, r_mu_k), r_o_mu_k)| (aa_k + instance.cc + gamma1) * r_mu_k + g1 * r_o_mu_k)
|
||||
.map(|((aa_k, r_mu_k), r_o_mu_k)| {
|
||||
(aa_k + instance.cc + gamma1) * r_mu_k + g1 * r_o_mu_k
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_gamma11_bytes = zkcm_gamma11
|
||||
@@ -300,9 +300,12 @@ impl SpendProof {
|
||||
.map(|x| x.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_kappa_k = r_lk.iter()
|
||||
let zkcm_kappa_k = r_lk
|
||||
.iter()
|
||||
.zip(r_r_lk.iter())
|
||||
.map(|(r_k, r_r_k)| params.pk_rp().alpha + params.pk_rp().beta * r_k + grparams.gen2() * r_r_k)
|
||||
.map(|(r_k, r_r_k)| {
|
||||
params.pk_rp().alpha + params.pk_rp().beta * r_k + grparams.gen2() * r_r_k
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_kappa_k_bytes = zkcm_kappa_k
|
||||
@@ -323,7 +326,7 @@ impl SpendProof {
|
||||
.chain(zkcm_ss_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_kappa_k_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_tt_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref())),
|
||||
);
|
||||
|
||||
// compute response for each witness
|
||||
@@ -375,58 +378,59 @@ impl SpendProof {
|
||||
+ grparams.gen2() * self.response_r
|
||||
+ verification_key.alpha * (Scalar::one() - self.challenge)
|
||||
+ self
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta_g2.iter())
|
||||
.map(|(attr, beta_i)| beta_i * attr)
|
||||
.sum::<G2Projective>();
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta_g2.iter())
|
||||
.map(|(attr, beta_i)| beta_i * attr)
|
||||
.sum::<G2Projective>();
|
||||
|
||||
|
||||
let zkcm_aa = self.response_o_a
|
||||
let zkcm_aa = self
|
||||
.response_o_a
|
||||
.iter()
|
||||
.zip(self.response_l.iter())
|
||||
.zip(instance.aa.iter())
|
||||
.map(|((resp_o_a_k, resp_l_k), aa_k)| g1 * resp_o_a_k + gamma1 * resp_l_k + aa_k * self.challenge)
|
||||
.map(|((resp_o_a_k, resp_l_k), aa_k)| {
|
||||
g1 * resp_o_a_k + gamma1 * resp_l_k + aa_k * self.challenge
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_aa_bytes = zkcm_aa
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
let zkcm_aa_bytes = zkcm_aa.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_cc = g1 * self.response_o_c
|
||||
+ gamma1 * self.response_attributes[1]
|
||||
+ instance.cc * self.challenge;
|
||||
|
||||
let zkcm_ss = self.response_mu
|
||||
let zkcm_ss = self
|
||||
.response_mu
|
||||
.iter()
|
||||
.zip(instance.ss.iter())
|
||||
.map(|(resp_mu_k, ss_k)| grparams.delta() * resp_mu_k + ss_k * self.challenge)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_ss_bytes = zkcm_ss
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
let zkcm_ss_bytes = zkcm_ss.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_tt = self.response_mu
|
||||
let zkcm_tt = self
|
||||
.response_mu
|
||||
.iter()
|
||||
.zip(rr.iter())
|
||||
.zip(instance.tt.iter())
|
||||
.map(|((resp_mu_k, rr_k), tt_k)| g1 * self.response_attributes[0] + (g1 * rr_k) * resp_mu_k + tt_k * self.challenge)
|
||||
.map(|((resp_mu_k, rr_k), tt_k)| {
|
||||
g1 * self.response_attributes[0] + (g1 * rr_k) * resp_mu_k + tt_k * self.challenge
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_tt_bytes = zkcm_tt
|
||||
.iter()
|
||||
.map(|x| x.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
let zkcm_tt_bytes = zkcm_tt.iter().map(|x| x.to_bytes()).collect::<Vec<_>>();
|
||||
|
||||
let zkcm_gamma11 = instance.aa
|
||||
let zkcm_gamma11 = instance
|
||||
.aa
|
||||
.iter()
|
||||
.zip(self.response_mu.iter())
|
||||
.zip(self.response_o_mu.iter())
|
||||
.map(|((aa_k, resp_mu_k), resp_o_mu_k)| (aa_k + instance.cc + gamma1) * resp_mu_k
|
||||
+ g1 * resp_o_mu_k + gamma1 * self.challenge)
|
||||
.map(|((aa_k, resp_mu_k), resp_o_mu_k)| {
|
||||
(aa_k + instance.cc + gamma1) * resp_mu_k
|
||||
+ g1 * resp_o_mu_k
|
||||
+ gamma1 * self.challenge
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_gamma11_bytes = zkcm_gamma11
|
||||
@@ -434,12 +438,17 @@ impl SpendProof {
|
||||
.map(|x| x.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
let zkcm_kappa_k = instance.kappa_k
|
||||
let zkcm_kappa_k = instance
|
||||
.kappa_k
|
||||
.iter()
|
||||
.zip(self.response_r_l.iter())
|
||||
.zip(self.response_l.iter())
|
||||
.map(|((kappa_k, resp_r_k), resp_r_l_k)| kappa_k * self.challenge + grparams.gen2() * resp_r_k + params.pk_rp().alpha * (Scalar::one() - self.challenge) + params.pk_rp().beta * resp_r_l_k)
|
||||
.map(|((kappa_k, resp_r_k), resp_r_l_k)| {
|
||||
kappa_k * self.challenge
|
||||
+ grparams.gen2() * resp_r_k
|
||||
+ params.pk_rp().alpha * (Scalar::one() - self.challenge)
|
||||
+ params.pk_rp().beta * resp_r_l_k
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zkcm_kappa_k_bytes = zkcm_kappa_k
|
||||
@@ -460,7 +469,7 @@ impl SpendProof {
|
||||
.chain(zkcm_ss_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_kappa_k_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_tt_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref()))
|
||||
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref())),
|
||||
);
|
||||
|
||||
challenge == self.challenge
|
||||
@@ -492,7 +501,8 @@ impl SpendProof {
|
||||
|
||||
let mut bytes: Vec<u8> = Vec::with_capacity(
|
||||
96 + (rrl_len + rl_len + roa_len + rmu_len + romu_len + rattributes_len) * 8
|
||||
+ (rrl_len + rl_len + roa_len + rmu_len + romu_len + rattributes_len) * 32);
|
||||
+ (rrl_len + rl_len + roa_len + rmu_len + romu_len + rattributes_len) * 32,
|
||||
);
|
||||
|
||||
bytes.extend_from_slice(&challenge_bytes);
|
||||
bytes.extend_from_slice(&response_r_bytes);
|
||||
@@ -529,9 +539,7 @@ impl SpendProof {
|
||||
}
|
||||
|
||||
bytes
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for SpendProof {
|
||||
@@ -540,8 +548,7 @@ impl TryFrom<&[u8]> for SpendProof {
|
||||
fn try_from(bytes: &[u8]) -> Result<SpendProof> {
|
||||
if bytes.len() < 336 || (bytes.len() - 96 - 48) % 32 != 0 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"tried to deserialize proof of spending with bytes of invalid length"
|
||||
.to_string(),
|
||||
"tried to deserialize proof of spending with bytes of invalid length".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -571,10 +578,9 @@ impl TryFrom<&[u8]> for SpendProof {
|
||||
let rrl_len = u64::from_le_bytes(bytes[idx..idx + 8].try_into().unwrap());
|
||||
idx += 8;
|
||||
if bytes[idx..].len() < rrl_len as usize * 32 {
|
||||
return Err(
|
||||
CompactEcashError::Deserialization(
|
||||
"tried to deserialize response_r_l".to_string()),
|
||||
);
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"tried to deserialize response_r_l".to_string(),
|
||||
));
|
||||
}
|
||||
let rrl_end = idx + rrl_len as usize * 32;
|
||||
let response_r_l = try_deserialize_scalar_vec(
|
||||
@@ -625,7 +631,11 @@ impl TryFrom<&[u8]> for SpendProof {
|
||||
CompactEcashError::Deserialization("Failed to deserialize response_mu".to_string()),
|
||||
)?;
|
||||
|
||||
let response_o_mu_len = u64::from_le_bytes(bytes[response_mu_end..response_mu_end + 8].try_into().unwrap());
|
||||
let response_o_mu_len = u64::from_le_bytes(
|
||||
bytes[response_mu_end..response_mu_end + 8]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
let response_o_mu_end = response_mu_end + 8;
|
||||
if bytes[response_o_mu_end..].len() < response_o_mu_len as usize * 32 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
@@ -639,21 +649,27 @@ impl TryFrom<&[u8]> for SpendProof {
|
||||
CompactEcashError::Deserialization("Failed to deserialize response_o_mu".to_string()),
|
||||
)?;
|
||||
|
||||
let response_attributes_len = u64::from_le_bytes(bytes[response_o_mu_end..response_o_mu_end + 8].try_into().unwrap());
|
||||
let response_attributes_len = u64::from_le_bytes(
|
||||
bytes[response_o_mu_end..response_o_mu_end + 8]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
let response_attributes_end = response_o_mu_end + 8;
|
||||
if bytes[response_attributes_end..].len() < response_attributes_len as usize * 32 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"tried to deserialize response_attributes".to_string(),
|
||||
));
|
||||
}
|
||||
let response_attributes_end = response_attributes_end + response_attributes_len as usize * 32;
|
||||
let response_attributes_end =
|
||||
response_attributes_end + response_attributes_len as usize * 32;
|
||||
let response_attributes = try_deserialize_scalar_vec(
|
||||
response_attributes_len,
|
||||
&bytes[response_o_mu_end + 8..response_attributes_end],
|
||||
CompactEcashError::Deserialization("Failed to deserialize response_attributes".to_string()),
|
||||
CompactEcashError::Deserialization(
|
||||
"Failed to deserialize response_attributes".to_string(),
|
||||
),
|
||||
)?;
|
||||
|
||||
|
||||
// Construct the SpendProof struct from the deserialized data
|
||||
let spend_proof = SpendProof {
|
||||
challenge,
|
||||
@@ -677,24 +693,24 @@ mod tests {
|
||||
use rand::thread_rng;
|
||||
|
||||
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
|
||||
use crate::scheme::{pseudorandom_f_delta_v, pseudorandom_f_g_v};
|
||||
use crate::scheme::aggregation::aggregate_verification_keys;
|
||||
use crate::scheme::keygen::{PublicKeyUser, ttp_keygen, VerificationKeyAuth};
|
||||
use crate::scheme::PayInfo;
|
||||
use crate::scheme::keygen::{ttp_keygen, PublicKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::setup::setup;
|
||||
use crate::scheme::PayInfo;
|
||||
use crate::scheme::{pseudorandom_f_delta_v, pseudorandom_f_g_v};
|
||||
use crate::utils::hash_to_scalar;
|
||||
|
||||
#[test]
|
||||
fn spend_proof_construct_and_verify() {
|
||||
let _rng = thread_rng();
|
||||
let L = 32;
|
||||
let params = setup(L);
|
||||
let ll = 32;
|
||||
let params = setup(ll);
|
||||
let grparams = params.grp();
|
||||
let sk = grparams.random_scalar();
|
||||
let _pk_user = PublicKeyUser {
|
||||
pk: grparams.gen1() * sk,
|
||||
};
|
||||
let authorities_keypairs = ttp_keygen(&grparams, 2, 3).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(grparams, 2, 3).unwrap();
|
||||
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.verification_key())
|
||||
@@ -715,10 +731,10 @@ mod tests {
|
||||
let kappa = grparams.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 o_a = grparams.random_scalar();
|
||||
let o_c = grparams.random_scalar();
|
||||
@@ -732,8 +748,8 @@ mod tests {
|
||||
let rr = hash_to_scalar(pay_info.info);
|
||||
|
||||
// evaluate the pseudorandom functions
|
||||
let ss = pseudorandom_f_delta_v(&grparams, v, l);
|
||||
let tt = g1 * sk + pseudorandom_f_g_v(&grparams, v, l) * rr;
|
||||
let ss = pseudorandom_f_delta_v(grparams, v, l);
|
||||
let tt = g1 * sk + pseudorandom_f_g_v(grparams, v, l) * rr;
|
||||
|
||||
// compute values mu, o_mu, lambda, o_lambda
|
||||
let mu: Scalar = (v + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
|
||||
@@ -767,7 +783,8 @@ mod tests {
|
||||
r_k: vec![r_l],
|
||||
};
|
||||
|
||||
let zk_proof = SpendProof::construct(¶ms, &instance, &witness, &verification_key, &[rr]);
|
||||
let zk_proof =
|
||||
SpendProof::construct(¶ms, &instance, &witness, &verification_key, &[rr]);
|
||||
assert!(zk_proof.verify(¶ms, &instance, &verification_key, &[rr]));
|
||||
|
||||
let zk_proof_bytes = zk_proof.to_bytes();
|
||||
|
||||
@@ -5,10 +5,12 @@ use group::GroupEncoding;
|
||||
use itertools::izip;
|
||||
|
||||
use crate::error::{CompactEcashError, 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;
|
||||
use crate::utils::{try_deserialize_g1_projective, try_deserialize_scalar_vec, try_deserialize_scalar};
|
||||
use crate::utils::{
|
||||
try_deserialize_g1_projective, try_deserialize_scalar, try_deserialize_scalar_vec,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
@@ -59,7 +61,7 @@ impl TryFrom<&[u8]> for WithdrawalReqInstance {
|
||||
let mut pc_coms_end: usize = 0;
|
||||
for i in 0..pc_coms_len {
|
||||
let start = (104 + i * 48) as usize;
|
||||
let end = (start + 48) as usize;
|
||||
let end = start + 48;
|
||||
let pc_i_bytes = bytes[start..end].try_into().unwrap();
|
||||
let pc_i = try_deserialize_g1_projective(
|
||||
&pc_i_bytes,
|
||||
@@ -90,7 +92,7 @@ impl TryFrom<&[u8]> for WithdrawalReqInstance {
|
||||
impl WithdrawalReqInstance {
|
||||
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||
let pc_coms_len = self.pc_coms.len();
|
||||
let mut bytes = Vec::with_capacity(8 + (pc_coms_len + 3) as usize * 48);
|
||||
let mut bytes = Vec::with_capacity(8 + (pc_coms_len + 3) * 48);
|
||||
bytes.extend_from_slice(self.com.to_bytes().as_ref());
|
||||
bytes.extend_from_slice(self.h.to_bytes().as_ref());
|
||||
bytes.extend_from_slice(&pc_coms_len.to_le_bytes());
|
||||
@@ -137,10 +139,10 @@ impl WithdrawalReqProof {
|
||||
// compute zkp commitments for each instance
|
||||
let zkcm_com = params.gen1() * r_com_opening
|
||||
+ r_attributes
|
||||
.iter()
|
||||
.zip(params.gammas().iter())
|
||||
.map(|(rm_i, gamma_i)| gamma_i * rm_i)
|
||||
.sum::<G1Projective>();
|
||||
.iter()
|
||||
.zip(params.gammas().iter())
|
||||
.map(|(rm_i, gamma_i)| gamma_i * rm_i)
|
||||
.sum::<G1Projective>();
|
||||
|
||||
let zkcm_pedcom = r_pedcom_openings
|
||||
.iter()
|
||||
@@ -202,21 +204,21 @@ impl WithdrawalReqProof {
|
||||
let zkcm_com = instance.com * self.challenge
|
||||
+ params.gen1() * self.response_opening
|
||||
+ self
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(params.gammas().iter())
|
||||
.map(|(m_i, gamma_i)| gamma_i * m_i)
|
||||
.sum::<G1Projective>();
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(params.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 + params.gen1() * resp_o_j + instance.h * resp_m_j
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
.map(|(cm_j, resp_o_j, resp_m_j)| {
|
||||
cm_j * self.challenge + params.gen1() * resp_o_j + instance.h * resp_m_j
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zk_commitment_user_sk =
|
||||
instance.pk_user.pk * self.challenge + params.gen1() * self.response_attributes[0];
|
||||
@@ -246,13 +248,14 @@ impl WithdrawalReqProof {
|
||||
challenge == self.challenge
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8>{
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let challenge_bytes = self.challenge.to_bytes();
|
||||
let response_opening_bytes = self.response_opening.to_bytes();
|
||||
let ro_len = self.response_openings.len() as u64;
|
||||
let ra_len = self.response_attributes.len() as u64;
|
||||
|
||||
let mut bytes = Vec::with_capacity(32 + 32 + 8 + ro_len as usize * 32 + 8 + ra_len as usize * 32);
|
||||
let mut bytes =
|
||||
Vec::with_capacity(32 + 32 + 8 + ro_len as usize * 32 + 8 + ra_len as usize * 32);
|
||||
bytes.extend_from_slice(&challenge_bytes);
|
||||
bytes.extend_from_slice(&response_opening_bytes);
|
||||
bytes.extend_from_slice(&ro_len.to_le_bytes());
|
||||
@@ -273,8 +276,7 @@ impl TryFrom<&[u8]> for WithdrawalReqProof {
|
||||
fn try_from(bytes: &[u8]) -> Result<WithdrawalReqProof> {
|
||||
if bytes.len() < 32 + 32 + 16 + 32 + 32 || (bytes.len() - 16) % 32 != 0 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"tried to deserialize proof of withdrawal with bytes of invalid length"
|
||||
.to_string(),
|
||||
"tried to deserialize proof of withdrawal with bytes of invalid length".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -299,26 +301,29 @@ impl TryFrom<&[u8]> for WithdrawalReqProof {
|
||||
let ro_len = u64::from_le_bytes(bytes[idx..idx + 8].try_into().unwrap());
|
||||
idx += 8;
|
||||
if bytes[idx..].len() < ro_len as usize * 32 + 8 {
|
||||
return Err(
|
||||
CompactEcashError::Deserialization(
|
||||
"tried to deserialize response openings".to_string()),
|
||||
);
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"tried to deserialize response openings".to_string(),
|
||||
));
|
||||
}
|
||||
let ro_end = idx + ro_len as usize * 32;
|
||||
let response_openings = try_deserialize_scalar_vec(
|
||||
ro_len,
|
||||
&bytes[idx..ro_end],
|
||||
CompactEcashError::Deserialization("Failed to deserialize openings response".to_string()),
|
||||
CompactEcashError::Deserialization(
|
||||
"Failed to deserialize openings response".to_string(),
|
||||
),
|
||||
)?;
|
||||
|
||||
let ra_len = u64::from_le_bytes(bytes[ro_end..ro_end + 8].try_into().unwrap());
|
||||
let response_attributes = try_deserialize_scalar_vec(
|
||||
ra_len,
|
||||
&bytes[ro_end + 8..],
|
||||
CompactEcashError::Deserialization("Failed to deserialize attributes response".to_string()),
|
||||
CompactEcashError::Deserialization(
|
||||
"Failed to deserialize attributes response".to_string(),
|
||||
),
|
||||
)?;
|
||||
|
||||
Ok(WithdrawalReqProof{
|
||||
Ok(WithdrawalReqProof {
|
||||
challenge,
|
||||
response_opening,
|
||||
response_openings,
|
||||
@@ -327,7 +332,6 @@ impl TryFrom<&[u8]> for WithdrawalReqProof {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use group::Group;
|
||||
@@ -374,10 +378,10 @@ mod tests {
|
||||
let com_opening = params.random_scalar();
|
||||
let com = params.gen1() * com_opening
|
||||
+ attr
|
||||
.iter()
|
||||
.zip(params.gammas())
|
||||
.map(|(&m, gamma)| gamma * m)
|
||||
.sum::<G1Projective>();
|
||||
.iter()
|
||||
.zip(params.gammas())
|
||||
.map(|(&m, gamma)| gamma * m)
|
||||
.sum::<G1Projective>();
|
||||
let h = hash_g1(com.to_bytes());
|
||||
|
||||
let pc_openings = params.n_random_scalars(attr.len());
|
||||
|
||||
@@ -6,16 +6,16 @@ use bls12_381::{G2Prepared, G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::Attribute;
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::scheme::{PartialWallet, Wallet};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::setup::GroupParameters;
|
||||
use crate::scheme::withdrawal::RequestInfo;
|
||||
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>;
|
||||
@@ -27,10 +27,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() {
|
||||
@@ -158,7 +158,7 @@ pub fn aggregate_wallets(
|
||||
|
||||
let attributes = vec![sk_user.sk, req_info.get_v()];
|
||||
let aggregated_signature =
|
||||
aggregate_signature_shares(¶ms, &verification_key, &attributes, &signature_shares)?;
|
||||
aggregate_signature_shares(params, verification_key, &attributes, &signature_shares)?;
|
||||
|
||||
Ok(Wallet {
|
||||
sig: aggregated_signature,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::{PayInfo, VerificationKeyAuth};
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::error::Result;
|
||||
use crate::scheme::keygen::PublicKeyUser;
|
||||
use crate::scheme::Payment;
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::PayInfo;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum IdentifyResult {
|
||||
@@ -11,7 +10,12 @@ pub enum IdentifyResult {
|
||||
DoubleSpendingPublicKeys(PublicKeyUser),
|
||||
}
|
||||
|
||||
pub fn identify(params: &Parameters, verification_key: &VerificationKeyAuth, payment1: Payment, payment2: Payment, pay_info1: PayInfo, pay_info2: PayInfo) -> Result<IdentifyResult> {
|
||||
pub fn identify(
|
||||
payment1: Payment,
|
||||
payment2: Payment,
|
||||
pay_info1: PayInfo,
|
||||
pay_info2: PayInfo,
|
||||
) -> Result<IdentifyResult> {
|
||||
let mut k = 0;
|
||||
let mut j = 0;
|
||||
for (id1, pay1_ss) in payment1.ss.iter().enumerate() {
|
||||
@@ -23,12 +27,17 @@ pub fn identify(params: &Parameters, verification_key: &VerificationKeyAuth, pay
|
||||
}
|
||||
}
|
||||
}
|
||||
if payment1.ss.iter().any(|pay1_ss| payment2.ss.contains(pay1_ss)) {
|
||||
if payment1
|
||||
.ss
|
||||
.iter()
|
||||
.any(|pay1_ss| payment2.ss.contains(pay1_ss))
|
||||
{
|
||||
if pay_info1 == pay_info2 {
|
||||
Ok(IdentifyResult::DuplicatePayInfo(pay_info1))
|
||||
} else {
|
||||
let rr_diff = payment1.rr[k] - payment2.rr[j];
|
||||
let pk = (payment2.tt[j] * payment1.rr[k] - payment1.tt[k] * payment2.rr[j]) * rr_diff.invert().unwrap();
|
||||
let pk = (payment2.tt[j] * payment1.rr[k] - payment1.tt[k] * payment2.rr[j])
|
||||
* rr_diff.invert().unwrap();
|
||||
let pk_user = PublicKeyUser { pk };
|
||||
Ok(IdentifyResult::DoubleSpendingPublicKeys(pk_user))
|
||||
}
|
||||
@@ -41,32 +50,36 @@ pub fn identify(params: &Parameters, verification_key: &VerificationKeyAuth, pay
|
||||
mod tests {
|
||||
use itertools::izip;
|
||||
|
||||
use crate::{aggregate_verification_keys, aggregate_wallets, generate_keypair_user, issue_verify, issue_wallet, PartialWallet, PayInfo, ttp_keygen, VerificationKeyAuth, withdrawal_request};
|
||||
use crate::scheme::identify::{identify, IdentifyResult};
|
||||
use crate::scheme::keygen::{PublicKeyUser, SecretKeyUser};
|
||||
use crate::scheme::setup::setup;
|
||||
use crate::{
|
||||
aggregate_verification_keys, aggregate_wallets, generate_keypair_user, issue_verify,
|
||||
issue_wallet, ttp_keygen, withdrawal_request, PartialWallet, PayInfo, VerificationKeyAuth,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn duplicate_payments_with_the_same_pay_info() {
|
||||
let L = 32;
|
||||
let params = setup(L);
|
||||
let ll = 32;
|
||||
let params = setup(ll);
|
||||
let grparams = params.grp();
|
||||
let user_keypair = generate_keypair_user(&grparams);
|
||||
let user_keypair = generate_keypair_user(grparams);
|
||||
|
||||
let (req, req_info) = withdrawal_request(grparams, &user_keypair.secret_key()).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(&grparams, 2, 3).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(grparams, 2, 3).unwrap();
|
||||
|
||||
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.verification_key())
|
||||
.collect();
|
||||
|
||||
let verification_key = aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
let verification_key =
|
||||
aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
|
||||
let mut wallet_blinded_signatures = Vec::new();
|
||||
for auth_keypair in authorities_keypairs {
|
||||
let blind_signature = issue_wallet(
|
||||
&grparams,
|
||||
grparams,
|
||||
auth_keypair.secret_key(),
|
||||
user_keypair.public_key(),
|
||||
&req,
|
||||
@@ -75,33 +88,38 @@ mod tests {
|
||||
}
|
||||
|
||||
let unblinded_wallet_shares: Vec<PartialWallet> = izip!(
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(&grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| {
|
||||
issue_verify(grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Aggregate partial wallets
|
||||
let aggr_wallet = aggregate_wallets(
|
||||
&grparams,
|
||||
grparams,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&unblinded_wallet_shares,
|
||||
&req_info,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Let's try to spend some coins
|
||||
let pay_info1 = PayInfo { info: [6u8; 32] };
|
||||
let spend_vv = 1;
|
||||
|
||||
let (payment1, _upd_wallet) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment1, _upd_wallet) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(¶ms, &verification_key, &pay_info1)
|
||||
@@ -113,31 +131,36 @@ mod tests {
|
||||
.unwrap());
|
||||
|
||||
let pay_info2 = pay_info1.clone();
|
||||
let identify_result = identify(¶ms, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(identify_result, IdentifyResult::DuplicatePayInfo(pay_info1.clone()));
|
||||
let identify_result =
|
||||
identify(payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(
|
||||
identify_result,
|
||||
IdentifyResult::DuplicatePayInfo(pay_info1.clone())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_if_two_different_payments() {
|
||||
let L = 32;
|
||||
let params = setup(L);
|
||||
let ll = 32;
|
||||
let params = setup(ll);
|
||||
let grparams = params.grp();
|
||||
let user_keypair = generate_keypair_user(&grparams);
|
||||
let user_keypair = generate_keypair_user(grparams);
|
||||
|
||||
let (req, req_info) = withdrawal_request(grparams, &user_keypair.secret_key()).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(&grparams, 2, 3).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(grparams, 2, 3).unwrap();
|
||||
|
||||
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.verification_key())
|
||||
.collect();
|
||||
|
||||
let verification_key = aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
let verification_key =
|
||||
aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
|
||||
let mut wallet_blinded_signatures = Vec::new();
|
||||
for auth_keypair in authorities_keypairs {
|
||||
let blind_signature = issue_wallet(
|
||||
&grparams,
|
||||
grparams,
|
||||
auth_keypair.secret_key(),
|
||||
user_keypair.public_key(),
|
||||
&req,
|
||||
@@ -146,89 +169,96 @@ mod tests {
|
||||
}
|
||||
|
||||
let unblinded_wallet_shares: Vec<PartialWallet> = izip!(
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(&grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| {
|
||||
issue_verify(grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Aggregate partial wallets
|
||||
let aggr_wallet = aggregate_wallets(
|
||||
&grparams,
|
||||
grparams,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&unblinded_wallet_shares,
|
||||
&req_info,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Let's try to spend some coins
|
||||
let pay_info1 = PayInfo { info: [6u8; 32] };
|
||||
let spend_vv = 1;
|
||||
|
||||
let (payment1, upd_wallet) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment1, upd_wallet) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(¶ms, &verification_key, &pay_info1)
|
||||
.unwrap());
|
||||
|
||||
|
||||
let pay_info2 = PayInfo { info: [7u8; 32] };
|
||||
let (payment2, _) = upd_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment2, _) = upd_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment2
|
||||
.spend_verify(¶ms, &verification_key, &pay_info2)
|
||||
.unwrap());
|
||||
|
||||
let identify_result = identify(¶ms, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
let identify_result =
|
||||
identify(payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(identify_result, IdentifyResult::NotADuplicatePayment);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_payments_with_one_repeating_serial_number_but_different_pay_info() {
|
||||
let L = 32;
|
||||
let params = setup(L);
|
||||
let ll = 32;
|
||||
let params = setup(ll);
|
||||
let grp = params.grp();
|
||||
let user_keypair = generate_keypair_user(&grp);
|
||||
let user_keypair = generate_keypair_user(grp);
|
||||
|
||||
// GENERATE KEYS FOR OTHER USERS
|
||||
let mut public_keys: Vec<PublicKeyUser> = Default::default();
|
||||
for _i in 0..50 {
|
||||
let sk = grp.random_scalar();
|
||||
let sk_user = SecretKeyUser { sk };
|
||||
let pk_user = sk_user.public_key(&grp);
|
||||
let pk_user = sk_user.public_key(grp);
|
||||
public_keys.push(pk_user.clone());
|
||||
}
|
||||
public_keys.push(user_keypair.public_key().clone());
|
||||
|
||||
|
||||
let (req, req_info) = withdrawal_request(grp, &user_keypair.secret_key()).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(&grp, 2, 3).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(grp, 2, 3).unwrap();
|
||||
|
||||
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.verification_key())
|
||||
.collect();
|
||||
|
||||
let verification_key = aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
let verification_key =
|
||||
aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
|
||||
let mut wallet_blinded_signatures = Vec::new();
|
||||
for auth_keypair in authorities_keypairs {
|
||||
let blind_signature = issue_wallet(
|
||||
&grp,
|
||||
grp,
|
||||
auth_keypair.secret_key(),
|
||||
user_keypair.public_key(),
|
||||
&req,
|
||||
@@ -237,33 +267,36 @@ mod tests {
|
||||
}
|
||||
|
||||
let unblinded_wallet_shares: Vec<PartialWallet> = izip!(
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
|
||||
// Aggregate partial wallets
|
||||
let aggr_wallet = aggregate_wallets(
|
||||
&grp,
|
||||
grp,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&unblinded_wallet_shares,
|
||||
&req_info,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Let's try to spend some coins
|
||||
let pay_info1 = PayInfo { info: [6u8; 32] };
|
||||
let spend_vv = 1;
|
||||
|
||||
let (payment1, _upd_wallet) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment1, _upd_wallet) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(¶ms, &verification_key, &pay_info1)
|
||||
@@ -275,54 +308,61 @@ mod tests {
|
||||
|
||||
let pay_info2 = PayInfo { info: [7u8; 32] };
|
||||
|
||||
let (payment2, _) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment2, _) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment2
|
||||
.spend_verify(¶ms, &verification_key, &pay_info2)
|
||||
.unwrap());
|
||||
|
||||
let identify_result = identify(¶ms, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key()));
|
||||
let identify_result =
|
||||
identify(payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(
|
||||
identify_result,
|
||||
IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_payments_with_multiple_repeating_serial_numbers_but_different_pay_info() {
|
||||
let L = 32;
|
||||
let params = setup(L);
|
||||
let ll = 32;
|
||||
let params = setup(ll);
|
||||
let grp = params.grp();
|
||||
let user_keypair = generate_keypair_user(&grp);
|
||||
let user_keypair = generate_keypair_user(grp);
|
||||
|
||||
// GENERATE KEYS FOR OTHER USERS
|
||||
let mut public_keys: Vec<PublicKeyUser> = Default::default();
|
||||
for i in 0..50 {
|
||||
for _ in 0..50 {
|
||||
let sk = grp.random_scalar();
|
||||
let sk_user = SecretKeyUser { sk };
|
||||
let pk_user = sk_user.public_key(&grp);
|
||||
let pk_user = sk_user.public_key(grp);
|
||||
public_keys.push(pk_user.clone());
|
||||
}
|
||||
public_keys.push(user_keypair.public_key().clone());
|
||||
|
||||
let (req, req_info) = withdrawal_request(grp, &user_keypair.secret_key()).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(&grp, 2, 3).unwrap();
|
||||
let authorities_keypairs = ttp_keygen(grp, 2, 3).unwrap();
|
||||
|
||||
let verification_keys_auth: Vec<VerificationKeyAuth> = authorities_keypairs
|
||||
.iter()
|
||||
.map(|keypair| keypair.verification_key())
|
||||
.collect();
|
||||
|
||||
let verification_key = aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
let verification_key =
|
||||
aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap();
|
||||
|
||||
let mut wallet_blinded_signatures = Vec::new();
|
||||
for auth_keypair in authorities_keypairs {
|
||||
let blind_signature = issue_wallet(
|
||||
&grp,
|
||||
grp,
|
||||
auth_keypair.secret_key(),
|
||||
user_keypair.public_key(),
|
||||
&req,
|
||||
@@ -331,33 +371,36 @@ mod tests {
|
||||
}
|
||||
|
||||
let unblinded_wallet_shares: Vec<PartialWallet> = izip!(
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
wallet_blinded_signatures.iter(),
|
||||
verification_keys_auth.iter()
|
||||
)
|
||||
.map(|(w, vk)| issue_verify(grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
|
||||
.collect();
|
||||
|
||||
// Aggregate partial wallets
|
||||
let aggr_wallet = aggregate_wallets(
|
||||
&grp,
|
||||
grp,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&unblinded_wallet_shares,
|
||||
&req_info,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Let's try to spend some coins
|
||||
let pay_info1 = PayInfo { info: [6u8; 32] };
|
||||
let spend_vv = 10;
|
||||
|
||||
let (payment1, _) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment1, _) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info1,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(¶ms, &verification_key, &pay_info1)
|
||||
@@ -368,17 +411,22 @@ mod tests {
|
||||
aggr_wallet.l.set(current_l - 10);
|
||||
|
||||
let pay_info2 = PayInfo { info: [7u8; 32] };
|
||||
let (payment2, _) = aggr_wallet.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
).unwrap();
|
||||
let (payment2, _) = aggr_wallet
|
||||
.spend(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
&pay_info2,
|
||||
false,
|
||||
spend_vv,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
let identify_result = identify(¶ms, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key()));
|
||||
let identify_result =
|
||||
identify(payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap();
|
||||
assert_eq!(
|
||||
identify_result,
|
||||
IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ impl SecretKeyAuth {
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let ys_len = self.ys.len();
|
||||
let mut bytes = Vec::with_capacity(8 + (ys_len + 1) as usize * 32);
|
||||
let mut bytes = Vec::with_capacity(8 + (ys_len + 1) * 32);
|
||||
bytes.extend_from_slice(&self.x.to_bytes());
|
||||
bytes.extend_from_slice(&ys_len.to_le_bytes());
|
||||
for y in self.ys.iter() {
|
||||
@@ -144,7 +144,7 @@ impl TryFrom<&[u8]> for VerificationKeyAuth {
|
||||
let mut beta_g1_end: u64 = 0;
|
||||
for i in 0..betas_len {
|
||||
let start = (104 + i * 48) as usize;
|
||||
let end = (start + 48) as usize;
|
||||
let end = start + 48;
|
||||
let beta_i_bytes = bytes[start..end].try_into().unwrap();
|
||||
let beta_i = try_deserialize_g1_projective(
|
||||
&beta_i_bytes,
|
||||
@@ -160,7 +160,7 @@ impl TryFrom<&[u8]> for VerificationKeyAuth {
|
||||
let mut beta_g2 = Vec::with_capacity(betas_len as usize);
|
||||
for i in 0..betas_len {
|
||||
let start = (beta_g1_end + i * 96) as usize;
|
||||
let end = (start + 96) as usize;
|
||||
let end = start + 96;
|
||||
let beta_i_bytes = bytes[start..end].try_into().unwrap();
|
||||
let beta_i = try_deserialize_g2_projective(
|
||||
&beta_i_bytes,
|
||||
|
||||
@@ -67,10 +67,10 @@ impl TryFrom<&[u8]> for PartialWallet {
|
||||
let idx_bytes: &[u8; 8] = &bytes[128..136].try_into().expect("Slice size != 8");
|
||||
|
||||
let sig = Signature::try_from(sig_bytes.as_slice()).unwrap();
|
||||
let v = Scalar::from_bytes(&v_bytes).unwrap();
|
||||
let idx = None;
|
||||
let v = Scalar::from_bytes(v_bytes).unwrap();
|
||||
let mut idx = None;
|
||||
if !idx_bytes.iter().all(|&x| x == 0) {
|
||||
let idx = Some(u64::from_le_bytes(*idx_bytes));
|
||||
idx = Some(u64::from_le_bytes(*idx_bytes));
|
||||
}
|
||||
|
||||
Ok(PartialWallet { sig, v, idx })
|
||||
@@ -117,7 +117,7 @@ impl Wallet {
|
||||
bench_flag: bool,
|
||||
spend_vv: u64,
|
||||
) -> Result<(Payment, &Self)> {
|
||||
if self.l() + spend_vv > params.L() {
|
||||
if self.l() + spend_vv > params.ll() {
|
||||
return Err(CompactEcashError::Spend(
|
||||
"The counter l is higher than max L".to_string(),
|
||||
));
|
||||
@@ -130,8 +130,8 @@ impl Wallet {
|
||||
let attributes = vec![sk_user.sk, self.v()];
|
||||
// compute kappa
|
||||
let kappa = compute_kappa(
|
||||
&grparams,
|
||||
&verification_key,
|
||||
grparams,
|
||||
verification_key,
|
||||
&attributes,
|
||||
sign_blinding_factor,
|
||||
);
|
||||
@@ -167,10 +167,10 @@ impl Wallet {
|
||||
aa.push(aa_k);
|
||||
|
||||
// evaluate the pseudorandom functions
|
||||
let ss_k = pseudorandom_f_delta_v(&grparams, self.v(), self.l() + k);
|
||||
let ss_k = pseudorandom_f_delta_v(grparams, self.v(), self.l() + k);
|
||||
ss.push(ss_k);
|
||||
let tt_k = grparams.gen1() * sk_user.sk
|
||||
+ pseudorandom_f_g_v(&grparams, self.v(), self.l() + k) * rr_k;
|
||||
+ pseudorandom_f_g_v(grparams, self.v(), self.l() + k) * rr_k;
|
||||
tt.push(tt_k);
|
||||
|
||||
// compute values mu, o_mu, lambda, o_lambda
|
||||
@@ -215,10 +215,10 @@ impl Wallet {
|
||||
r_k: r_k_vec,
|
||||
};
|
||||
let zk_proof = SpendProof::construct(
|
||||
¶ms,
|
||||
params,
|
||||
&spend_instance,
|
||||
&spend_witness,
|
||||
&verification_key,
|
||||
verification_key,
|
||||
&rr,
|
||||
);
|
||||
|
||||
@@ -267,7 +267,7 @@ impl TryFrom<&[u8]> for Wallet {
|
||||
let l_bytes: &[u8; 8] = &bytes[128..136].try_into().expect("Slice size != 8");
|
||||
|
||||
let sig = Signature::try_from(sig_bytes.as_slice()).unwrap();
|
||||
let v = Scalar::from_bytes(&v_bytes).unwrap();
|
||||
let v = Scalar::from_bytes(v_bytes).unwrap();
|
||||
let l = Cell::new(u64::from_le_bytes(*l_bytes));
|
||||
|
||||
Ok(Wallet { sig, v, l })
|
||||
@@ -394,7 +394,7 @@ impl Payment {
|
||||
|
||||
if !self
|
||||
.zk_proof
|
||||
.verify(¶ms, &instance, &verification_key, &self.rr)
|
||||
.verify(params, &instance, verification_key, &self.rr)
|
||||
{
|
||||
return Err(CompactEcashError::Spend(
|
||||
"ZkProof verification failed".to_string(),
|
||||
@@ -611,20 +611,22 @@ impl TryFrom<&[u8]> for Payment {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Getters, CopyGetters, Clone, PartialEq)]
|
||||
#[derive(Getters, CopyGetters)]
|
||||
pub struct EcashCredential {
|
||||
#[getset(get = "pub")]
|
||||
params: Parameters,
|
||||
#[getset(get = "pub")]
|
||||
payment: Payment,
|
||||
#[getset(get = "pub")]
|
||||
pay_info: PayInfo,
|
||||
//pub L : u64, ?
|
||||
#[getset(get = "pub")]
|
||||
epoch_id: u64,
|
||||
}
|
||||
|
||||
impl EcashCredential {
|
||||
pub fn new(payment: Payment, pay_info: PayInfo, epoch_id: u64) -> Self {
|
||||
pub fn new(params: Parameters, payment: Payment, pay_info: PayInfo, epoch_id: u64) -> Self {
|
||||
EcashCredential {
|
||||
params,
|
||||
payment,
|
||||
pay_info,
|
||||
epoch_id,
|
||||
@@ -632,31 +634,68 @@ impl EcashCredential {
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut ecash_bytes = self.payment.to_bytes();
|
||||
ecash_bytes.extend_from_slice(&self.pay_info.info);
|
||||
ecash_bytes.extend_from_slice(&self.epoch_id.to_be_bytes());
|
||||
let params_bytes = self.params.to_bytes();
|
||||
let payment_bytes = self.payment.to_bytes();
|
||||
|
||||
ecash_bytes
|
||||
let mut bytes =
|
||||
Vec::with_capacity(params_bytes.len() + payment_bytes.len() + 32 + 8 + 8 + 8);
|
||||
|
||||
bytes.extend_from_slice(&(params_bytes.len() as u64).to_be_bytes());
|
||||
bytes.extend_from_slice(&self.params.to_bytes());
|
||||
bytes.extend_from_slice(&(payment_bytes.len() as u64).to_be_bytes());
|
||||
bytes.extend_from_slice(&self.payment.to_bytes());
|
||||
bytes.extend_from_slice(&self.pay_info.info);
|
||||
bytes.extend_from_slice(&self.epoch_id.to_be_bytes());
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for EcashCredential {
|
||||
type Error = CompactEcashError;
|
||||
fn try_from(bytes: &[u8]) -> Result<Self> {
|
||||
if bytes.len() < 32 + 8 {
|
||||
if bytes.len() < 32 + 8 + 8 + 8 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for EcashCredential deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
let payment_bytes = &bytes[..bytes.len() - 32 - 8];
|
||||
let payment = Payment::try_from(payment_bytes)?;
|
||||
let mut index = 0;
|
||||
let params_len = u64::from_be_bytes(bytes[index..index + 8].try_into().unwrap()) as usize;
|
||||
index += 8;
|
||||
|
||||
if bytes[index..].len() < params_len {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for EcashCredential deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let params = Parameters::try_from(&bytes[index..index + params_len])?;
|
||||
index += params_len;
|
||||
|
||||
let payment_len = u64::from_be_bytes(bytes[index..index + 8].try_into().unwrap()) as usize;
|
||||
index += 8;
|
||||
|
||||
if bytes[index..].len() < payment_len {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for EcashCredential deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
let payment = Payment::try_from(&bytes[index..index + payment_len])?;
|
||||
index += payment_len;
|
||||
|
||||
if bytes[index..].len() != 32 + 8 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for EcashCredential deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let pay_info = PayInfo {
|
||||
info: bytes[bytes.len() - 32 - 8..bytes.len() - 8]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
info: bytes[index..index + 32].try_into().unwrap(),
|
||||
};
|
||||
let epoch_id = u64::from_be_bytes(bytes[bytes.len() - 8..].try_into().unwrap());
|
||||
index += 32;
|
||||
let epoch_id = u64::from_be_bytes(bytes[index..index + 8].try_into().unwrap());
|
||||
Ok(EcashCredential {
|
||||
params,
|
||||
payment,
|
||||
pay_info,
|
||||
epoch_id,
|
||||
|
||||
@@ -2,10 +2,11 @@ use std::collections::HashMap;
|
||||
|
||||
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar};
|
||||
use ff::Field;
|
||||
use group::Curve;
|
||||
use rand::thread_rng;
|
||||
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::utils::{hash_g1, Signature};
|
||||
use crate::utils::{hash_g1, try_deserialize_g2_projective, Signature};
|
||||
|
||||
const ATTRIBUTES_LEN: usize = 3;
|
||||
|
||||
@@ -59,7 +60,9 @@ impl GroupParameters {
|
||||
self.gammas.get(2)
|
||||
}
|
||||
|
||||
pub(crate) fn delta(&self) -> &G1Projective { &self.delta }
|
||||
pub(crate) fn delta(&self) -> &G1Projective {
|
||||
&self.delta
|
||||
}
|
||||
|
||||
pub fn random_scalar(&self) -> Scalar {
|
||||
// lazily-initialized thread-local random number generator, seeded by the system
|
||||
@@ -103,7 +106,7 @@ pub struct Parameters {
|
||||
/// Public Key for range proof verification
|
||||
pk_rp: PublicKeyRP,
|
||||
/// Max value of wallet
|
||||
L: u64,
|
||||
ll: u64,
|
||||
/// list of signatures for values l in [0, L]
|
||||
signs: HashMap<u64, Signature>,
|
||||
}
|
||||
@@ -115,48 +118,114 @@ impl Parameters {
|
||||
pub fn pk_rp(&self) -> &PublicKeyRP {
|
||||
&self.pk_rp
|
||||
}
|
||||
pub fn L(&self) -> u64 {
|
||||
self.L
|
||||
pub fn ll(&self) -> u64 {
|
||||
self.ll
|
||||
}
|
||||
pub fn signs(&self) -> &HashMap<u64, Signature> {
|
||||
&self.signs
|
||||
}
|
||||
pub fn get_sign_by_idx(&self, idx: u64) -> Result<&Signature> {
|
||||
match self.signs.get(&idx) {
|
||||
Some(val) => return Ok(val),
|
||||
None => {
|
||||
return Err(CompactEcashError::RangeProofOutOfBound(
|
||||
"Cannot find the range proof signature for the given value. \
|
||||
Some(val) => Ok(val),
|
||||
None => Err(CompactEcashError::RangeProofOutOfBound(
|
||||
"Cannot find the range proof signature for the given value. \
|
||||
Check if the requested value is within the bound 0..L"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
.to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
//we omit grp as it is fixed
|
||||
let pk_rp_alpha_bytes = self.pk_rp.alpha.to_affine().to_compressed();
|
||||
let pk_rp_beta_bytes = self.pk_rp.beta.to_affine().to_compressed();
|
||||
let l_bytes = self.ll.to_be_bytes();
|
||||
|
||||
let signs_bytes: Vec<u8> = self
|
||||
.signs
|
||||
.iter()
|
||||
.flat_map(|(_, value)| value.to_bytes())
|
||||
.collect();
|
||||
|
||||
let mut bytes = Vec::with_capacity(96 + 96 + 8 + signs_bytes.len());
|
||||
|
||||
bytes.extend_from_slice(&pk_rp_alpha_bytes);
|
||||
bytes.extend_from_slice(&pk_rp_beta_bytes);
|
||||
bytes.extend_from_slice(&l_bytes);
|
||||
bytes.extend_from_slice(&signs_bytes);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup(L: u64) -> Parameters {
|
||||
impl TryFrom<&[u8]> for Parameters {
|
||||
type Error = CompactEcashError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self> {
|
||||
if bytes.len() < 96 + 96 + 8 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for Parameters deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
let pk_rp_alpha_bytes: [u8; 96] = bytes[..96].try_into().unwrap();
|
||||
let pk_rp_beta_bytes: [u8; 96] = bytes[96..192].try_into().unwrap();
|
||||
let ll = u64::from_be_bytes(bytes[192..200].try_into().unwrap());
|
||||
|
||||
let mut index = 200;
|
||||
if bytes[index..].len() != ll as usize * 96 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for Parameters signatures deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let pk_rp_alpha = try_deserialize_g2_projective(
|
||||
&pk_rp_alpha_bytes,
|
||||
CompactEcashError::Deserialization("Failed to deserialize pk_rp_alpha".to_string()),
|
||||
)?;
|
||||
|
||||
let pk_rp_beta = try_deserialize_g2_projective(
|
||||
&pk_rp_beta_bytes,
|
||||
CompactEcashError::Deserialization("Failed to deserialize pk_rp_beta".to_string()),
|
||||
)?;
|
||||
|
||||
let grp_params = GroupParameters::new()?;
|
||||
let pk_rp = PublicKeyRP {
|
||||
alpha: pk_rp_alpha,
|
||||
beta: pk_rp_beta,
|
||||
};
|
||||
|
||||
let mut signs = HashMap::new();
|
||||
|
||||
for l in 0..ll {
|
||||
let sign = Signature::try_from(&bytes[index..index + 96])?;
|
||||
signs.insert(l, sign);
|
||||
index += 96;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
grp: grp_params,
|
||||
pk_rp,
|
||||
ll,
|
||||
signs,
|
||||
})
|
||||
}
|
||||
}
|
||||
pub fn setup(ll: u64) -> Parameters {
|
||||
let grp = GroupParameters::new().unwrap();
|
||||
let x = grp.random_scalar();
|
||||
let y = grp.random_scalar();
|
||||
let sk_rp = SecretKeyRP { x, y };
|
||||
let pk_rp = sk_rp.public_key(&grp);
|
||||
let mut signs = HashMap::new();
|
||||
for l in 0..L {
|
||||
for l in 0..ll {
|
||||
let r = grp.random_scalar();
|
||||
let h = grp.gen1() * r;
|
||||
signs.insert(
|
||||
l,
|
||||
Signature {
|
||||
0: h,
|
||||
1: h * (x + y * Scalar::from(l)),
|
||||
},
|
||||
);
|
||||
signs.insert(l, Signature(h, h * (x + y * Scalar::from(l))));
|
||||
}
|
||||
Parameters {
|
||||
grp,
|
||||
pk_rp,
|
||||
L,
|
||||
ll,
|
||||
signs,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ pub fn withdrawal_request(
|
||||
pc_coms_openings: pc_coms_openings.clone(),
|
||||
};
|
||||
|
||||
let zk_proof = WithdrawalReqProof::construct(¶ms, &instance, &witness);
|
||||
let zk_proof = WithdrawalReqProof::construct(params, &instance, &witness);
|
||||
|
||||
let req = WithdrawalRequest {
|
||||
com_hash,
|
||||
@@ -329,7 +329,7 @@ pub fn issue_wallet(
|
||||
pc_coms: withdrawal_req.pc_coms.clone(),
|
||||
pk_user,
|
||||
};
|
||||
if !withdrawal_req.zk_proof.verify(¶ms, &instance) {
|
||||
if !withdrawal_req.zk_proof.verify(params, &instance) {
|
||||
return Err(CompactEcashError::WithdrawalRequestVerification(
|
||||
"Failed to verify the proof of knowledge".to_string(),
|
||||
));
|
||||
@@ -374,7 +374,7 @@ pub fn issue_verify(
|
||||
|
||||
let unblinded_c = c - blinding_removers;
|
||||
|
||||
let attr = vec![sk_user.sk, req_info.v];
|
||||
let attr = [sk_user.sk, req_info.v];
|
||||
|
||||
let signed_attributes = attr
|
||||
.iter()
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ nym-node = { path = "../nym-node" }
|
||||
nym-api-requests = { path = "../nym-api/nym-api-requests" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
|
||||
nym-coconut-interface = { path = "../common/coconut-interface" }
|
||||
nym_compact_ecash = { path = "../common/nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../common/nym_offline_compact_ecash" }
|
||||
nym-config = { path = "../common/config" }
|
||||
nym-credentials = { path = "../common/credentials" }
|
||||
nym-crypto = { path = "../common/crypto" }
|
||||
|
||||
@@ -25,7 +25,7 @@ nym-pemstore = { path = "../../common/pemstore" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
|
||||
nym-coconut-interface = { path = "../../common/coconut-interface" }
|
||||
nym_compact_ecash = {path = "../../common/nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = {path = "../../common/nym_offline_compact_ecash" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
|
||||
[dependencies.tungstenite]
|
||||
|
||||
@@ -250,12 +250,10 @@ where
|
||||
let aggregated_verification_key =
|
||||
nym_credentials::obtain_aggregate_verification_key(&credential_api_clients).await?;
|
||||
|
||||
let params = setup(100); //SW: TEMPORARY VALUE, Take from credential?
|
||||
|
||||
credential
|
||||
.payment()
|
||||
.spend_verify(
|
||||
¶ms,
|
||||
&credential.params(),
|
||||
&aggregated_verification_key,
|
||||
&credential.pay_info(),
|
||||
)
|
||||
|
||||
@@ -30,7 +30,7 @@ use crate::node::{
|
||||
active_clients::ActiveClientsStore,
|
||||
websocket::{
|
||||
connection_handler::{
|
||||
coconut::CoconutVerifier, AuthenticatedHandler, ClientDetails, InitialAuthResult,
|
||||
coconut::EcashVerifier, AuthenticatedHandler, ClientDetails, InitialAuthResult,
|
||||
SocketStream,
|
||||
},
|
||||
message_receiver::{IsActive, IsActiveRequestSender},
|
||||
@@ -94,7 +94,7 @@ pub(crate) struct FreshHandler<R, S, St> {
|
||||
pub(crate) outbound_mix_sender: MixForwardingSender,
|
||||
pub(crate) socket_connection: SocketStream<S>,
|
||||
pub(crate) storage: St,
|
||||
pub(crate) coconut_verifier: Arc<CoconutVerifier>,
|
||||
pub(crate) ecash_verifier: Arc<EcashVerifier>,
|
||||
}
|
||||
|
||||
impl<R, S, St> FreshHandler<R, S, St>
|
||||
@@ -115,7 +115,7 @@ where
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
storage: St,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
coconut_verifier: Arc<CoconutVerifier>,
|
||||
ecash_verifier: Arc<EcashVerifier>,
|
||||
) -> Self {
|
||||
FreshHandler {
|
||||
rng,
|
||||
@@ -125,7 +125,7 @@ where
|
||||
socket_connection: SocketStream::RawTcp(conn),
|
||||
local_identity,
|
||||
storage,
|
||||
coconut_verifier,
|
||||
ecash_verifier,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier;
|
||||
use crate::node::client_handling::websocket::connection_handler::coconut::EcashVerifier;
|
||||
use crate::node::client_handling::websocket::connection_handler::FreshHandler;
|
||||
use crate::node::storage::Storage;
|
||||
use log::*;
|
||||
@@ -18,7 +18,7 @@ pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
only_coconut_credentials: bool,
|
||||
pub(crate) coconut_verifier: Arc<CoconutVerifier>,
|
||||
pub(crate) ecash_verifier: Arc<EcashVerifier>,
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
@@ -26,13 +26,13 @@ impl Listener {
|
||||
address: SocketAddr,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
only_coconut_credentials: bool,
|
||||
coconut_verifier: Arc<CoconutVerifier>,
|
||||
ecash_verifier: Arc<EcashVerifier>,
|
||||
) -> Self {
|
||||
Listener {
|
||||
address,
|
||||
local_identity,
|
||||
only_coconut_credentials,
|
||||
coconut_verifier,
|
||||
ecash_verifier,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ impl Listener {
|
||||
Arc::clone(&self.local_identity),
|
||||
storage.clone(),
|
||||
active_clients_store.clone(),
|
||||
Arc::clone(&self.coconut_verifier),
|
||||
Arc::clone(&self.ecash_verifier),
|
||||
);
|
||||
let shutdown = shutdown.clone().named(format!("ClientConnectionHandler_{remote_addr}"));
|
||||
tokio::spawn(async move { handle.start_handling(shutdown).await });
|
||||
|
||||
+12
-5
@@ -15,7 +15,7 @@ use crate::node::client_handling::embedded_network_requester::{
|
||||
LocalNetworkRequesterHandle, MessageRouter,
|
||||
};
|
||||
use crate::node::client_handling::websocket;
|
||||
use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier;
|
||||
use crate::node::client_handling::websocket::connection_handler::coconut::EcashVerifier;
|
||||
use crate::node::helpers::{initialise_main_storage, load_network_requester_config};
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use crate::node::statistics::collector::GatewayStatisticsCollector;
|
||||
@@ -215,7 +215,7 @@ impl<St> Gateway<St> {
|
||||
forwarding_channel: MixForwardingSender,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
shutdown: TaskClient,
|
||||
coconut_verifier: Arc<CoconutVerifier>,
|
||||
ecash_verifier: Arc<EcashVerifier>,
|
||||
) where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
@@ -230,7 +230,7 @@ impl<St> Gateway<St> {
|
||||
listening_address,
|
||||
Arc::clone(&self.identity_keypair),
|
||||
self.config.gateway.only_coconut_credentials,
|
||||
coconut_verifier,
|
||||
ecash_verifier,
|
||||
)
|
||||
.start(
|
||||
forwarding_channel,
|
||||
@@ -449,9 +449,9 @@ impl<St> Gateway<St> {
|
||||
|
||||
let shutdown = TaskManager::new(10);
|
||||
|
||||
let coconut_verifier = {
|
||||
let ecash_verifier = {
|
||||
let nyxd_client = self.random_nyxd_client()?;
|
||||
CoconutVerifier::new(nyxd_client)
|
||||
EcashVerifier::new(nyxd_client)
|
||||
};
|
||||
|
||||
let mix_forwarding_channel =
|
||||
@@ -521,6 +521,13 @@ impl<St> Gateway<St> {
|
||||
.with_maybe_network_request_filter(nr_request_filter)
|
||||
.start(shutdown.subscribe().named("http-api"))?;
|
||||
|
||||
self.start_client_websocket_listener(
|
||||
mix_forwarding_channel,
|
||||
active_clients_store,
|
||||
shutdown.subscribe().named("websocket::Listener"),
|
||||
Arc::new(ecash_verifier),
|
||||
);
|
||||
|
||||
// Once this is a bit more mature, make this a commandline flag instead of a compile time
|
||||
// flag
|
||||
#[cfg(feature = "wireguard")]
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ nym-bandwidth-controller = { path = "../common/bandwidth-controller" }
|
||||
nym-coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
nym-coconut-dkg-common = { path = "../common/cosmwasm-smart-contracts/coconut-dkg" }
|
||||
nym-coconut-interface = { path = "../common/coconut-interface" }
|
||||
nym_compact_ecash = { path = "../common/nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../common/nym_offline_compact_ecash" }
|
||||
nym-ephemera-common = { path = "../common/cosmwasm-smart-contracts/ephemera" }
|
||||
nym-config = { path = "../common/config" }
|
||||
cosmwasm-std = { workspace = true }
|
||||
|
||||
@@ -15,7 +15,7 @@ serde = { workspace = true, features = ["derive"] }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
nym-coconut-interface = { path = "../../common/coconut-interface" }
|
||||
nym_compact_ecash = { path = "../../common/nym_offline_compact_ecash" }
|
||||
nym-compact-ecash = { path = "../../common/nym_offline_compact_ecash" }
|
||||
nym-mixnet-contract-common = { path= "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false }
|
||||
|
||||
|
||||
@@ -3,29 +3,32 @@
|
||||
|
||||
use cosmrs::AccountId;
|
||||
use getset::{CopyGetters, Getters};
|
||||
use nym_coconut_interface::{Credential, VerificationKey};
|
||||
use nym_compact_ecash::{error::CompactEcashError, scheme::withdrawal::WithdrawalRequest};
|
||||
use nym_compact_ecash::{
|
||||
error::CompactEcashError,
|
||||
scheme::{withdrawal::WithdrawalRequest, EcashCredential},
|
||||
VerificationKeyAuth,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Getters, CopyGetters)]
|
||||
pub struct VerifyCredentialBody {
|
||||
#[getset(get = "pub")]
|
||||
credential: Credential,
|
||||
#[getset(get = "pub")]
|
||||
proposal_id: u64,
|
||||
credential: EcashCredential,
|
||||
//#[getset(get = "pub")]
|
||||
//proposal_id: u64,
|
||||
#[getset(get = "pub")]
|
||||
gateway_cosmos_addr: AccountId,
|
||||
}
|
||||
|
||||
impl VerifyCredentialBody {
|
||||
pub fn new(
|
||||
credential: Credential,
|
||||
proposal_id: u64,
|
||||
credential: EcashCredential,
|
||||
//proposal_id: u64,
|
||||
gateway_cosmos_addr: AccountId,
|
||||
) -> VerifyCredentialBody {
|
||||
VerifyCredentialBody {
|
||||
credential,
|
||||
proposal_id,
|
||||
//proposal_id,
|
||||
gateway_cosmos_addr,
|
||||
}
|
||||
}
|
||||
@@ -142,11 +145,11 @@ impl BlindedSignatureResponse {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VerificationKeyResponse {
|
||||
pub key: VerificationKey,
|
||||
pub key: VerificationKeyAuth,
|
||||
}
|
||||
|
||||
impl VerificationKeyResponse {
|
||||
pub fn new(key: VerificationKey) -> VerificationKeyResponse {
|
||||
pub fn new(key: VerificationKeyAuth) -> VerificationKeyResponse {
|
||||
VerificationKeyResponse { key }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::nyxd;
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_compact_ecash::VerificationKeyAuth;
|
||||
use nym_credentials::coconut::utils::obtain_aggregate_verification_key;
|
||||
use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[async_trait]
|
||||
@@ -28,8 +28,8 @@ impl QueryCommunicationChannel {
|
||||
impl APICommunicationChannel for QueryCommunicationChannel {
|
||||
async fn aggregated_verification_key(&self, epoch_id: EpochId) -> Result<VerificationKeyAuth> {
|
||||
let client = self.nyxd_client.0.read().await;
|
||||
let coconut_api_clients = all_coconut_api_clients(client.deref(), epoch_id).await?;
|
||||
let vk = obtain_aggregate_verification_key(&coconut_api_clients).await?;
|
||||
let ecash_api_clients = all_ecash_api_clients(client.deref(), epoch_id).await?;
|
||||
let vk = obtain_aggregate_verification_key(&ecash_api_clients).await?;
|
||||
Ok(vk)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user