explicit aliases for ExpirationDate and TicketType
This commit is contained in:
@@ -6,13 +6,16 @@ use time::{Duration, PrimitiveDateTime, Time};
|
||||
pub use time::{Date, OffsetDateTime};
|
||||
|
||||
pub trait EcashTime {
|
||||
fn ecash_unix_timestamp(&self) -> u64 {
|
||||
fn ecash_unix_timestamp(&self) -> u32 {
|
||||
let ts = self.ecash_datetime().unix_timestamp();
|
||||
|
||||
// just panic on pre-1970 timestamps...
|
||||
assert!(ts > 0);
|
||||
|
||||
ts as u64
|
||||
// and on anything in 22nd century...
|
||||
assert!(ts <= u32::MAX as i64);
|
||||
|
||||
ts as u32
|
||||
}
|
||||
|
||||
fn ecash_date(&self) -> Date {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/// Specifies the maximum validity of the issued ticketbooks.
|
||||
pub const TICKETBOOK_VALIDITY_DAYS: u64 = 7;
|
||||
pub const TICKETBOOK_VALIDITY_DAYS: u32 = 7;
|
||||
|
||||
/// Specifies the number of tickets in each issued ticketbook.
|
||||
pub const TICKETBOOK_SIZE: u64 = 50;
|
||||
|
||||
@@ -9,9 +9,9 @@ pub const PUBLIC_ATTRIBUTES_LEN: usize = 2; //expiration date and ticket type
|
||||
pub const PRIVATE_ATTRIBUTES_LEN: usize = 2; //user and wallet secret
|
||||
pub const ATTRIBUTES_LEN: usize = PUBLIC_ATTRIBUTES_LEN + PRIVATE_ATTRIBUTES_LEN; // number of attributes encoded in a single zk-nym credential
|
||||
|
||||
pub const CRED_VALIDITY_PERIOD_DAYS: u64 = TICKETBOOK_VALIDITY_DAYS;
|
||||
pub const CRED_VALIDITY_PERIOD_DAYS: u32 = TICKETBOOK_VALIDITY_DAYS;
|
||||
|
||||
pub(crate) const SECONDS_PER_DAY: u64 = 86400;
|
||||
pub(crate) const SECONDS_PER_DAY: u32 = 86400;
|
||||
|
||||
/// Total number of tickets in each issued ticket book.
|
||||
pub const NB_TICKETS: u64 = TICKETBOOK_SIZE;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::utils::try_deserialize_g1_projective;
|
||||
use crate::CompactEcashError;
|
||||
use bls12_381::G1Projective;
|
||||
use crate::{CompactEcashError, EncodedDate, EncodedTicketType};
|
||||
use bls12_381::{G1Projective, Scalar};
|
||||
use group::Curve;
|
||||
use std::any::{type_name, Any};
|
||||
|
||||
@@ -35,3 +35,27 @@ pub(crate) fn recover_g1_tuple<T: Any>(
|
||||
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
pub(crate) fn date_scalar(date: EncodedDate) -> Scalar {
|
||||
Scalar::from(date as u64)
|
||||
}
|
||||
|
||||
// TODO: this will not work for **all** scalars,
|
||||
// but timestamps have extremely (relatively speaking) limited range,
|
||||
// so this should be fine
|
||||
pub(crate) fn scalar_date(scalar: &Scalar) -> EncodedDate {
|
||||
let b = scalar.to_bytes();
|
||||
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]) as EncodedDate
|
||||
}
|
||||
|
||||
pub(crate) fn type_scalar(t_type: EncodedTicketType) -> Scalar {
|
||||
Scalar::from(t_type as u64)
|
||||
}
|
||||
|
||||
// TODO: this will not work for **all** scalars,
|
||||
// but ticket types have extremely (relatively speaking) limited range,
|
||||
// so this should be fine
|
||||
pub(crate) fn scalar_type(scalar: &Scalar) -> EncodedTicketType {
|
||||
let b = scalar.to_bytes();
|
||||
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]) as EncodedTicketType
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ mod traits;
|
||||
pub mod utils;
|
||||
|
||||
pub type Attribute = Scalar;
|
||||
pub type EncodedTicketType = u8;
|
||||
pub type EncodedDate = u32;
|
||||
|
||||
pub fn ecash_parameters() -> &'static setup::Parameters {
|
||||
static ECASH_PARAMS: OnceLock<setup::Parameters> = OnceLock::new();
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use core::iter::Sum;
|
||||
use core::ops::Mul;
|
||||
|
||||
use bls12_381::{G2Prepared, G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::common_types::{PartialSignature, Signature, SignatureShare, SignerIndex};
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::scheme::expiration_date_signatures::scalar_date;
|
||||
use crate::helpers::{scalar_date, scalar_type};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::withdrawal::RequestInfo;
|
||||
use crate::scheme::{PartialWallet, Wallet, WalletSignatures};
|
||||
use crate::utils::{
|
||||
check_bilinear_pairing, perform_lagrangian_interpolation_at_origin, scalar_type,
|
||||
};
|
||||
use crate::utils::{check_bilinear_pairing, perform_lagrangian_interpolation_at_origin};
|
||||
use crate::{ecash_group_parameters, Attribute};
|
||||
use bls12_381::{G2Prepared, G2Projective, Scalar};
|
||||
use core::iter::Sum;
|
||||
use core::ops::Mul;
|
||||
use group::Curve;
|
||||
use itertools::Itertools;
|
||||
|
||||
pub(crate) trait Aggregatable: Sized {
|
||||
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::common_types::{Signature, SignerIndex};
|
||||
use crate::constants;
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::helpers::date_scalar;
|
||||
use crate::scheme::keygen::{SecretKeyAuth, VerificationKeyAuth};
|
||||
use crate::utils::generate_lagrangian_coefficients_at_origin;
|
||||
use crate::utils::{batch_verify_signatures, hash_g1};
|
||||
use crate::{constants, EncodedDate};
|
||||
use bls12_381::{G1Projective, Scalar};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -19,8 +20,8 @@ pub type PartialExpirationDateSignature = ExpirationDateSignature;
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
pub struct AnnotatedExpirationDateSignature {
|
||||
pub signature: ExpirationDateSignature,
|
||||
pub expiration_timestamp: u64,
|
||||
pub spending_timestamp: u64,
|
||||
pub expiration_timestamp: EncodedDate,
|
||||
pub spending_timestamp: EncodedDate,
|
||||
}
|
||||
|
||||
impl Borrow<ExpirationDateSignature> for AnnotatedExpirationDateSignature {
|
||||
@@ -66,17 +67,17 @@ where
|
||||
/// The validity period is determined by the constant `CRED_VALIDITY_PERIOD` in the `constants` module.
|
||||
pub fn sign_expiration_date(
|
||||
sk_auth: &SecretKeyAuth,
|
||||
expiration_unix_timestamp: u64,
|
||||
expiration_unix_timestamp: EncodedDate,
|
||||
) -> Result<Vec<AnnotatedExpirationDateSignature>> {
|
||||
if sk_auth.ys.len() < 3 {
|
||||
return Err(CompactEcashError::KeyTooShort);
|
||||
}
|
||||
let m0: Scalar = Scalar::from(expiration_unix_timestamp);
|
||||
let m0: Scalar = date_scalar(expiration_unix_timestamp);
|
||||
let m2: Scalar = constants::TYPE_EXP;
|
||||
|
||||
let partial_s_exponent = sk_auth.x + sk_auth.ys[0] * m0 + sk_auth.ys[2] * m2;
|
||||
|
||||
let sign_expiration = |offset: u64| {
|
||||
let sign_expiration = |offset: u32| {
|
||||
// we produce tuples of (assuming CRED_VALIDITY_PERIOD_DAYS = 30):
|
||||
// (expiration, expiration - 29)
|
||||
// (expiration, expiration - 28)
|
||||
@@ -84,7 +85,7 @@ pub fn sign_expiration_date(
|
||||
// (expiration, expiration)
|
||||
let spending_unix_timestamp = expiration_unix_timestamp
|
||||
- ((constants::CRED_VALIDITY_PERIOD_DAYS - offset - 1) * constants::SECONDS_PER_DAY);
|
||||
let m1: Scalar = Scalar::from(spending_unix_timestamp);
|
||||
let m1: Scalar = date_scalar(spending_unix_timestamp);
|
||||
// Compute the hash
|
||||
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
|
||||
// Sign the attributes by performing scalar-point multiplications and accumulating the result
|
||||
@@ -136,22 +137,22 @@ pub fn sign_expiration_date(
|
||||
pub fn verify_valid_dates_signatures<B>(
|
||||
vk: &VerificationKeyAuth,
|
||||
signatures: &[B],
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
) -> Result<()>
|
||||
where
|
||||
B: Borrow<ExpirationDateSignature>,
|
||||
{
|
||||
let m0: Scalar = Scalar::from(expiration_date);
|
||||
let m0: Scalar = date_scalar(expiration_date);
|
||||
let m2: Scalar = constants::TYPE_EXP;
|
||||
|
||||
let partially_signed = vk.alpha + vk.beta_g2[0] * m0 + vk.beta_g2[2] * m2;
|
||||
let mut pairing_terms = Vec::with_capacity(signatures.len());
|
||||
|
||||
for (i, sig) in signatures.iter().enumerate() {
|
||||
let l = i as u64;
|
||||
let l = i as u32;
|
||||
let valid_date = expiration_date
|
||||
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
|
||||
let m1: Scalar = Scalar::from(valid_date);
|
||||
let m1: Scalar = date_scalar(valid_date);
|
||||
|
||||
// Compute the hash
|
||||
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
|
||||
@@ -199,7 +200,7 @@ where
|
||||
///
|
||||
fn _aggregate_expiration_signatures<B>(
|
||||
vk: &VerificationKeyAuth,
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
signatures_shares: &[ExpirationDateSignatureShare<B>],
|
||||
validate_shares: bool,
|
||||
) -> Result<Vec<ExpirationDateSignature>>
|
||||
@@ -244,12 +245,12 @@ where
|
||||
let mut aggregated_date_signatures: Vec<ExpirationDateSignature> =
|
||||
Vec::with_capacity(constants::CRED_VALIDITY_PERIOD_DAYS as usize);
|
||||
|
||||
let m0: Scalar = Scalar::from(expiration_date);
|
||||
let m0: Scalar = date_scalar(expiration_date);
|
||||
|
||||
for l in 0..constants::CRED_VALIDITY_PERIOD_DAYS {
|
||||
let valid_date = expiration_date
|
||||
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
|
||||
let m1: Scalar = Scalar::from(valid_date);
|
||||
let m1: Scalar = date_scalar(valid_date);
|
||||
// Compute the hash
|
||||
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
|
||||
|
||||
@@ -299,7 +300,7 @@ where
|
||||
///
|
||||
pub fn aggregate_expiration_signatures<B>(
|
||||
vk: &VerificationKeyAuth,
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
signatures_shares: &[ExpirationDateSignatureShare<B>],
|
||||
) -> Result<Vec<ExpirationDateSignature>>
|
||||
where
|
||||
@@ -314,7 +315,7 @@ where
|
||||
/// It further annotates the result with timestamp information
|
||||
pub fn aggregate_annotated_expiration_signatures(
|
||||
vk: &VerificationKeyAuth,
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
signatures_shares: &[ExpirationDateSignatureShare<AnnotatedExpirationDateSignature>],
|
||||
) -> Result<Vec<AnnotatedExpirationDateSignature>> {
|
||||
// it's sufficient to just verify the first share as if the rest of them don't match,
|
||||
@@ -332,7 +333,7 @@ pub fn aggregate_annotated_expiration_signatures(
|
||||
return Err(CompactEcashError::ExpirationDateSignatureVerification);
|
||||
}
|
||||
|
||||
let l = i as u64;
|
||||
let l = i as u32;
|
||||
let expected_spending = sig.expiration_timestamp
|
||||
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
|
||||
|
||||
@@ -361,7 +362,7 @@ pub fn aggregate_annotated_expiration_signatures(
|
||||
/// It is expected the caller has already pre-validated them via manual calls to `verify_valid_dates_signatures`
|
||||
pub fn unchecked_aggregate_expiration_signatures(
|
||||
vk: &VerificationKeyAuth,
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
signatures_shares: &[ExpirationDateSignatureShare],
|
||||
) -> Result<Vec<ExpirationDateSignature>> {
|
||||
_aggregate_expiration_signatures(vk, expiration_date, signatures_shares, false)
|
||||
@@ -383,13 +384,13 @@ pub fn unchecked_aggregate_expiration_signatures(
|
||||
/// If a valid index is found, returns `Ok(index)`. If no valid index is found
|
||||
/// (i.e., `spend_date` is earlier than `expiration_date - 30`), returns `Err(InvalidDateError)`.
|
||||
///
|
||||
pub fn find_index(spend_date: u64, expiration_date: u64) -> Result<usize> {
|
||||
pub fn find_index(spend_date: EncodedDate, expiration_date: EncodedDate) -> Result<usize> {
|
||||
let start_date =
|
||||
expiration_date - ((constants::CRED_VALIDITY_PERIOD_DAYS - 1) * constants::SECONDS_PER_DAY);
|
||||
|
||||
if spend_date >= start_date {
|
||||
let index_a = ((spend_date - start_date) / constants::SECONDS_PER_DAY) as usize;
|
||||
if index_a as u64 >= constants::CRED_VALIDITY_PERIOD_DAYS {
|
||||
if index_a as u32 >= constants::CRED_VALIDITY_PERIOD_DAYS {
|
||||
Err(CompactEcashError::SpendDateTooLate)
|
||||
} else {
|
||||
Ok(index_a)
|
||||
@@ -399,18 +400,6 @@ pub fn find_index(spend_date: u64, expiration_date: u64) -> Result<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date_scalar(date: u64) -> Scalar {
|
||||
Scalar::from(date)
|
||||
}
|
||||
|
||||
// TODO: this will not work for **all** scalars,
|
||||
// but timestamps have extremely (relatively speaking) limited range,
|
||||
// so this should be fine
|
||||
pub fn scalar_date(scalar: &Scalar) -> u64 {
|
||||
let b = scalar.to_bytes();
|
||||
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -54,7 +54,6 @@ pub fn identify(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::scheme::expiration_date_signatures::date_scalar;
|
||||
use crate::scheme::identify::{identify, IdentifyResult};
|
||||
use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser};
|
||||
use crate::setup::Parameters;
|
||||
@@ -165,12 +164,12 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info1, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let payment2 = payment1.clone();
|
||||
assert!(payment2
|
||||
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info1, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info1);
|
||||
@@ -275,7 +274,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info1, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let pay_info2 = PayInfo {
|
||||
@@ -295,7 +294,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment2
|
||||
.spend_verify(&verification_key, &pay_info2, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info2, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info2);
|
||||
@@ -411,7 +410,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info1, spend_date)
|
||||
.is_ok());
|
||||
|
||||
// let's reverse the spending counter in the wallet to create a double spending payment
|
||||
@@ -435,7 +434,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment2
|
||||
.spend_verify(&verification_key, &pay_info2, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info2, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info2);
|
||||
@@ -555,7 +554,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(payment1
|
||||
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info1, spend_date)
|
||||
.is_ok());
|
||||
|
||||
// let's reverse the spending counter in the wallet to create a double spending payment
|
||||
|
||||
@@ -97,10 +97,6 @@ impl SecretKeyAuth {
|
||||
self.ys.len()
|
||||
}
|
||||
|
||||
pub(crate) fn get_y_by_idx(&self, i: usize) -> Option<&Scalar> {
|
||||
self.ys.get(i)
|
||||
}
|
||||
|
||||
pub fn verification_key(&self) -> VerificationKeyAuth {
|
||||
let params = ecash_group_parameters();
|
||||
let g1 = params.gen1();
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
|
||||
use crate::common_types::{Signature, SignerIndex};
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::helpers::{date_scalar, type_scalar};
|
||||
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
|
||||
use crate::scheme::coin_indices_signatures::CoinIndexSignature;
|
||||
use crate::scheme::expiration_date_signatures::{date_scalar, find_index, ExpirationDateSignature};
|
||||
use crate::scheme::expiration_date_signatures::{find_index, ExpirationDateSignature};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::setup::{GroupParameters, Parameters};
|
||||
use crate::traits::Bytable;
|
||||
use crate::utils::{
|
||||
batch_verify_signatures, check_bilinear_pairing, hash_to_scalar, try_deserialize_scalar,
|
||||
};
|
||||
use crate::Base58;
|
||||
use crate::{constants, ecash_group_parameters};
|
||||
use crate::{Base58, EncodedDate, EncodedTicketType};
|
||||
use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
@@ -228,7 +229,7 @@ impl Wallet {
|
||||
spend_value: u64,
|
||||
valid_dates_signatures: &[ExpirationDateSignature],
|
||||
coin_indices_signatures: &[CoinIndexSignature],
|
||||
spend_date_timestamp: u64,
|
||||
spend_date_timestamp: EncodedDate,
|
||||
) -> Result<Payment> {
|
||||
self.check_remaining_allowance(params, spend_value)?;
|
||||
|
||||
@@ -269,8 +270,8 @@ pub struct WalletSignatures {
|
||||
#[zeroize(skip)]
|
||||
sig: Signature,
|
||||
v: Scalar,
|
||||
expiration_date_timestamp: u64,
|
||||
t_type: u64,
|
||||
expiration_date_timestamp: EncodedDate,
|
||||
t_type: EncodedTicketType,
|
||||
}
|
||||
|
||||
impl WalletSignatures {
|
||||
@@ -314,8 +315,8 @@ pub fn compute_pay_info_hash(pay_info: &PayInfo, k: u64) -> Scalar {
|
||||
}
|
||||
|
||||
impl WalletSignatures {
|
||||
// signature size (96) + secret size (32) + expiration size (8) + t_type (8)
|
||||
pub const SERIALISED_SIZE: usize = 144;
|
||||
// signature size (96) + secret size (32) + expiration size (4) + t_type (1)
|
||||
pub const SERIALISED_SIZE: usize = 133;
|
||||
|
||||
pub fn signature(&self) -> &Signature {
|
||||
&self.sig
|
||||
@@ -335,8 +336,8 @@ impl WalletSignatures {
|
||||
let mut bytes = [0u8; Self::SERIALISED_SIZE];
|
||||
bytes[0..96].copy_from_slice(&self.sig.to_bytes());
|
||||
bytes[96..128].copy_from_slice(&self.v.to_bytes());
|
||||
bytes[128..136].copy_from_slice(&self.expiration_date_timestamp.to_be_bytes());
|
||||
bytes[136..144].copy_from_slice(&self.t_type.to_be_bytes());
|
||||
bytes[128..132].copy_from_slice(&self.expiration_date_timestamp.to_be_bytes());
|
||||
bytes[132] = self.t_type;
|
||||
bytes
|
||||
}
|
||||
|
||||
@@ -356,15 +357,12 @@ impl WalletSignatures {
|
||||
let v_bytes: &[u8; 32] = &bytes[96..128].try_into().unwrap();
|
||||
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let expiration_date_bytes = bytes[128..136].try_into().unwrap();
|
||||
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let t_type_bytes = bytes[136..].try_into().unwrap();
|
||||
let expiration_date_bytes = bytes[128..132].try_into().unwrap();
|
||||
|
||||
let sig = Signature::try_from(sig_bytes.as_slice())?;
|
||||
let v = Scalar::from_bytes(v_bytes).unwrap();
|
||||
let expiration_date_timestamp = u64::from_be_bytes(expiration_date_bytes);
|
||||
let t_type = u64::from_be_bytes(t_type_bytes);
|
||||
let expiration_date_timestamp = EncodedDate::from_be_bytes(expiration_date_bytes);
|
||||
let t_type = bytes[132];
|
||||
|
||||
Ok(WalletSignatures {
|
||||
sig,
|
||||
@@ -401,7 +399,7 @@ impl WalletSignatures {
|
||||
spend_value: u64,
|
||||
valid_dates_signatures: &[BE],
|
||||
coin_indices_signatures: &[BI],
|
||||
spend_date_timestamp: u64,
|
||||
spend_date_timestamp: EncodedDate,
|
||||
) -> Result<Payment>
|
||||
where
|
||||
BI: Borrow<CoinIndexSignature>,
|
||||
@@ -596,7 +594,7 @@ fn pseudorandom_f_g_v(params: &GroupParameters, v: &Scalar, l: u64) -> Result<G1
|
||||
/// * `params` - A reference to the group parameters required for the computation.
|
||||
/// * `verification_key` - The global verification key of the signing authorities.
|
||||
/// * `attributes` - A slice of private attributes associated with the wallet.
|
||||
/// * `blinding_factor` - The blinding factor used used to randomise the wallet's signature.
|
||||
/// * `blinding_factor` - The blinding factor used to randomise the wallet's signature.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@@ -689,7 +687,7 @@ pub struct Payment {
|
||||
pub aa: Vec<G1Projective>,
|
||||
pub spend_value: u64,
|
||||
pub cc: G1Projective,
|
||||
pub t_type: u64,
|
||||
pub t_type: EncodedTicketType,
|
||||
pub zk_proof: SpendProof,
|
||||
}
|
||||
|
||||
@@ -720,7 +718,7 @@ impl Payment {
|
||||
return Err(CompactEcashError::SpendSignaturesValidity);
|
||||
}
|
||||
|
||||
let kappa_type = self.kappa + verification_key.beta_g2[3] * Scalar::from(self.t_type);
|
||||
let kappa_type = self.kappa + verification_key.beta_g2[3] * type_scalar(self.t_type);
|
||||
if !check_bilinear_pairing(
|
||||
&self.sig.h.to_affine(),
|
||||
&G2Prepared::from(kappa_type.to_affine()),
|
||||
@@ -950,7 +948,7 @@ impl Payment {
|
||||
&self,
|
||||
verification_key: &VerificationKeyAuth,
|
||||
pay_info: &PayInfo,
|
||||
spend_date: Scalar,
|
||||
spend_date: EncodedDate,
|
||||
) -> Result<()> {
|
||||
// check if all serial numbers are different
|
||||
self.no_duplicate_serial_numbers()?;
|
||||
@@ -959,7 +957,7 @@ impl Payment {
|
||||
// Verify whether the payment signature and kappa are correct
|
||||
self.check_signature_validity(verification_key)?;
|
||||
// Verify whether the expiration date signature and kappa_e are correct
|
||||
self.check_exp_signature_validity(verification_key, spend_date)?;
|
||||
self.check_exp_signature_validity(verification_key, date_scalar(spend_date))?;
|
||||
// Verify whether the coin indices signatures and kappa_k are correct
|
||||
self.batch_check_coin_index_signatures(verification_key)?;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::common_types::{BlindedSignature, Signature, SignerIndex};
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::helpers::{date_scalar, type_scalar};
|
||||
use crate::proofs::proof_withdrawal::{
|
||||
WithdrawalReqInstance, WithdrawalReqProof, WithdrawalReqWitness,
|
||||
};
|
||||
@@ -10,7 +11,7 @@ use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser, Verific
|
||||
use crate::scheme::setup::GroupParameters;
|
||||
use crate::scheme::PartialWallet;
|
||||
use crate::utils::{check_bilinear_pairing, hash_g1};
|
||||
use crate::{constants, ecash_group_parameters, Attribute};
|
||||
use crate::{constants, ecash_group_parameters, Attribute, EncodedDate, EncodedTicketType};
|
||||
use bls12_381::{multi_miller_loop, G1Projective, G2Prepared, G2Projective, Scalar};
|
||||
use group::{Curve, Group, GroupEncoding};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -141,28 +142,25 @@ fn compute_private_attribute_commitments(
|
||||
/// openings for private attributes, `v`, and the expiration date.
|
||||
pub fn withdrawal_request(
|
||||
sk_user: &SecretKeyUser,
|
||||
expiration_date: u64,
|
||||
t_type: u64,
|
||||
expiration_date: EncodedDate,
|
||||
t_type: EncodedTicketType,
|
||||
) -> Result<(WithdrawalRequest, RequestInfo)> {
|
||||
let params = ecash_group_parameters();
|
||||
// Generate random and unique wallet secret
|
||||
let v = params.random_scalar();
|
||||
let joined_commitment_opening = params.random_scalar();
|
||||
|
||||
let gamma = params.gammas();
|
||||
let expiration_date = date_scalar(expiration_date);
|
||||
let t_type = type_scalar(t_type);
|
||||
|
||||
// Compute joined commitment for all attributes (public and private)
|
||||
//SAFETY: params is static with length 3
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let joined_commitment: G1Projective = params.gen1() * joined_commitment_opening
|
||||
+ params.gamma_idx(0).unwrap() * sk_user.sk
|
||||
+ params.gamma_idx(1).unwrap() * v;
|
||||
let joined_commitment =
|
||||
params.gen1() * joined_commitment_opening + gamma[0] * sk_user.sk + gamma[1] * v;
|
||||
|
||||
// Compute commitment hash h
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let joined_commitment_hash = hash_g1(
|
||||
(joined_commitment
|
||||
+ params.gamma_idx(2).unwrap() * Scalar::from(expiration_date)
|
||||
+ params.gamma_idx(3).unwrap() * Scalar::from(t_type))
|
||||
.to_bytes(),
|
||||
);
|
||||
let joined_commitment_hash =
|
||||
hash_g1((joined_commitment + gamma[2] * expiration_date + gamma[3] * t_type).to_bytes());
|
||||
|
||||
// Compute Pedersen commitments for private attributes (wallet secret and user's secret)
|
||||
let private_attributes = vec![sk_user.sk, v];
|
||||
@@ -199,8 +197,8 @@ pub fn withdrawal_request(
|
||||
joined_commitment_opening,
|
||||
private_attributes_openings: private_attributes_openings.clone(),
|
||||
wallet_secret: v,
|
||||
expiration_date: Scalar::from(expiration_date),
|
||||
t_type: Scalar::from(t_type),
|
||||
expiration_date,
|
||||
t_type,
|
||||
},
|
||||
))
|
||||
}
|
||||
@@ -222,18 +220,17 @@ pub fn withdrawal_request(
|
||||
pub fn request_verify(
|
||||
req: &WithdrawalRequest,
|
||||
pk_user: PublicKeyUser,
|
||||
expiration_date: u64,
|
||||
t_type: u64,
|
||||
expiration_date: EncodedDate,
|
||||
t_type: EncodedTicketType,
|
||||
) -> Result<()> {
|
||||
let params = ecash_group_parameters();
|
||||
// Verify the joined commitment hash
|
||||
//SAFETY: params is static with length 3
|
||||
#[allow(clippy::unwrap_used)]
|
||||
|
||||
let gamma = params.gammas();
|
||||
let expiration_date = date_scalar(expiration_date);
|
||||
let t_type = type_scalar(t_type);
|
||||
|
||||
let expected_commitment_hash = hash_g1(
|
||||
(req.joined_commitment
|
||||
+ params.gamma_idx(2).unwrap() * Scalar::from(expiration_date)
|
||||
+ params.gamma_idx(3).unwrap() * Scalar::from(t_type))
|
||||
.to_bytes(),
|
||||
(req.joined_commitment + gamma[2] * expiration_date + gamma[3] * t_type).to_bytes(),
|
||||
);
|
||||
if req.joined_commitment_hash != expected_commitment_hash {
|
||||
return Err(CompactEcashError::WithdrawalRequestVerification);
|
||||
@@ -270,13 +267,10 @@ pub fn request_verify(
|
||||
/// authentication secret key index is out of bounds.
|
||||
fn sign_expiration_date(
|
||||
joined_commitment_hash: &G1Projective,
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
sk_auth: &SecretKeyAuth,
|
||||
) -> G1Projective {
|
||||
//SAFETY : this fn assumes a long enough key
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let yi = sk_auth.get_y_by_idx(2).unwrap();
|
||||
joined_commitment_hash * (yi * Scalar::from(expiration_date))
|
||||
joined_commitment_hash * (sk_auth.ys[2] * date_scalar(expiration_date))
|
||||
}
|
||||
|
||||
/// Signs a transaction type using a joined commitment hash and a secret key.
|
||||
@@ -296,13 +290,10 @@ fn sign_expiration_date(
|
||||
/// The resulting G1Projective point representing the signed ticket type.
|
||||
fn sign_t_type(
|
||||
joined_commitment_hash: &G1Projective,
|
||||
t_type: u64,
|
||||
t_type: EncodedTicketType,
|
||||
sk_auth: &SecretKeyAuth,
|
||||
) -> G1Projective {
|
||||
//SAFETY : this fn assumes a long enough key
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let yi = sk_auth.get_y_by_idx(3).unwrap();
|
||||
joined_commitment_hash * (yi * Scalar::from(t_type))
|
||||
joined_commitment_hash * (sk_auth.ys[3] * type_scalar(t_type))
|
||||
}
|
||||
|
||||
/// Issues a blinded signature for a withdrawal request, after verifying its integrity.
|
||||
@@ -327,8 +318,8 @@ pub fn issue(
|
||||
sk_auth: &SecretKeyAuth,
|
||||
pk_user: PublicKeyUser,
|
||||
withdrawal_req: &WithdrawalRequest,
|
||||
expiration_date: u64,
|
||||
t_type: u64,
|
||||
expiration_date: EncodedDate,
|
||||
t_type: EncodedTicketType,
|
||||
) -> Result<BlindedSignature> {
|
||||
// Verify the withdrawal request
|
||||
request_verify(withdrawal_req, pk_user, expiration_date, t_type)?;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
mod tests {
|
||||
use crate::error::Result;
|
||||
use crate::scheme::aggregation::{aggregate_verification_keys, aggregate_wallets};
|
||||
use crate::scheme::expiration_date_signatures::date_scalar;
|
||||
use crate::scheme::keygen::{
|
||||
generate_keypair_user, ttp_keygen, SecretKeyAuth, VerificationKeyAuth,
|
||||
};
|
||||
@@ -125,7 +124,7 @@ mod tests {
|
||||
)?;
|
||||
|
||||
assert!(payment
|
||||
.spend_verify(&verification_key, &pay_info, date_scalar(spend_date))
|
||||
.spend_verify(&verification_key, &pay_info, spend_date)
|
||||
.is_ok());
|
||||
|
||||
let payment_bytes = payment.to_bytes();
|
||||
|
||||
@@ -15,12 +15,13 @@ use crate::scheme::Payment;
|
||||
use crate::setup::Parameters;
|
||||
use crate::{
|
||||
aggregate_verification_keys, aggregate_wallets, constants, generate_keypair_user, issue,
|
||||
issue_verify, withdrawal_request, PartialWallet, PayInfo, VerificationKeyAuth,
|
||||
issue_verify, withdrawal_request, EncodedDate, EncodedTicketType, PartialWallet, PayInfo,
|
||||
VerificationKeyAuth,
|
||||
};
|
||||
use itertools::izip;
|
||||
|
||||
pub fn generate_expiration_date_signatures(
|
||||
expiration_date: u64,
|
||||
expiration_date: EncodedDate,
|
||||
secret_keys_authorities: &[&SecretKeyAuth],
|
||||
verification_keys_auth: &[VerificationKeyAuth],
|
||||
verification_key: &VerificationKeyAuth,
|
||||
@@ -82,8 +83,8 @@ pub fn generate_coin_indices_signatures(
|
||||
pub fn payment_from_keys_and_expiration_date(
|
||||
ecash_keypairs: &Vec<KeyPairAuth>,
|
||||
indices: &[SignerIndex],
|
||||
expiration_date: u64,
|
||||
t_type: u64,
|
||||
expiration_date: EncodedDate,
|
||||
t_type: EncodedTicketType,
|
||||
) -> Result<(Payment, PayInfo)> {
|
||||
let total_coins = 32;
|
||||
let params = Parameters::new(total_coins);
|
||||
|
||||
@@ -402,8 +402,3 @@ mod tests {
|
||||
assert_ne!(hash_to_scalar(msg1), hash_to_scalar(msg2));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scalar_type(scalar: &Scalar) -> u64 {
|
||||
let b = scalar.to_bytes();
|
||||
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user