diff --git a/common/credential-utils/src/recovery_storage.rs b/common/credential-utils/src/recovery_storage.rs index 3c9b8c17af..f003b562cd 100644 --- a/common/credential-utils/src/recovery_storage.rs +++ b/common/credential-utils/src/recovery_storage.rs @@ -8,6 +8,8 @@ use std::fs::{create_dir_all, read_dir, File}; use std::io::{Read, Write}; use std::path::PathBuf; +pub const DUMPED_VOUCHER_EXTENSION: &str = "credentialrecovery"; + pub struct RecoveryStorage { recovery_dir: PathBuf, } @@ -24,8 +26,10 @@ impl RecoveryStorage { let mut paths = vec![]; for entry in entries.flatten() { let path = entry.path(); - if path.is_file() { - paths.push(path) + if let Some(extension) = path.extension() { + if extension == DUMPED_VOUCHER_EXTENSION { + paths.push(path) + } } } @@ -47,15 +51,20 @@ impl RecoveryStorage { Ok(vouchers) } + pub fn voucher_filename(voucher: &IssuanceBandwidthCredential) -> String { + let prefix = voucher.typ().to_string(); + let suffix = voucher.blinded_g1_serial_number_bs58(); + format!("{prefix}-{suffix}.{DUMPED_VOUCHER_EXTENSION}") + } + pub fn insert_voucher(&self, voucher: &IssuanceBandwidthCredential) -> Result { - todo!() - // let file_name = voucher.tx_hash().to_string(); - // let file_path = self.recovery_dir.join(file_name); - // let mut file = File::create(&file_path)?; - // let buff = voucher.to_bytes(); - // file.write_all(&buff)?; - // - // Ok(file_path) + let file_name = Self::voucher_filename(voucher); + let file_path = self.recovery_dir.join(file_name); + let mut file = File::create(&file_path)?; + let buff = voucher.to_recovery_bytes(); + file.write_all(&buff)?; + + Ok(file_path) } pub fn remove_voucher(&self, file_name: String) -> Result<()> { diff --git a/common/credential-utils/src/utils.rs b/common/credential-utils/src/utils.rs index 7668b5f1b7..8e773a3225 100644 --- a/common/credential-utils/src/utils.rs +++ b/common/credential-utils/src/utils.rs @@ -5,6 +5,7 @@ use nym_bandwidth_controller::acquire::state::State; use nym_client_core::config::disk_persistence::CommonClientPaths; use nym_config::DEFAULT_DATA_DIR; use nym_credential_storage::persistent_storage::PersistentStorage; +use nym_credentials::coconut::bandwidth::CredentialType; use nym_validator_client::nyxd::contract_traits::{ dkg_query_client::EpochState, CoconutBandwidthSigningClient, DkgQueryClient, }; @@ -126,25 +127,33 @@ pub async fn recover_credentials( where C: DkgQueryClient + Send + Sync, { - todo!() - // let mut recovered_amount: u128 = 0; - // for voucher in recovery_storage.unconsumed_vouchers()? { - // let voucher_value = voucher.get_voucher_value(); - // recovered_amount += voucher_value.parse::()?; - // - // let state = State::new(voucher); - // let voucher = state.voucher.tx_hash(); - // if let Err(e) = - // nym_bandwidth_controller::acquire::get_credential(&state, client, shared_storage).await - // { - // error!("Could not recover deposit {voucher} due to {e}, try again later",) - // } else { - // info!("Converted deposit {voucher} to a credential, removing recovery data for it",); - // if let Err(e) = recovery_storage.remove_voucher(voucher.to_string()) { - // warn!("Could not remove recovery data: {e}"); - // } - // } - // } - // - // Ok(recovered_amount) + let mut recovered_amount: u128 = 0; + for voucher in recovery_storage.unconsumed_vouchers()? { + let voucher_value = match voucher.typ() { + CredentialType::Voucher => voucher.get_bandwidth_attribute(), + CredentialType::FreePass => { + error!("unimplemented recovery of free pass credentials"); + continue; + } + }; + recovered_amount += voucher_value.parse::()?; + + let voucher_name = RecoveryStorage::voucher_filename(&voucher); + let state = State::new(voucher); + + if let Err(e) = + nym_bandwidth_controller::acquire::get_credential(&state, client, shared_storage).await + { + error!("Could not recover deposit {voucher_name} due to {e}, try again later",) + } else { + info!( + "Converted deposit {voucher_name} to a credential, removing recovery data for it", + ); + if let Err(err) = recovery_storage.remove_voucher(voucher_name) { + warn!("Could not remove recovery data: {err}"); + } + } + } + + Ok(recovered_amount) } diff --git a/common/credentials/src/coconut/bandwidth/issuance.rs b/common/credentials/src/coconut/bandwidth/issuance.rs index 7078d358d5..3ef9352782 100644 --- a/common/credentials/src/coconut/bandwidth/issuance.rs +++ b/common/credentials/src/coconut/bandwidth/issuance.rs @@ -9,6 +9,7 @@ use crate::coconut::bandwidth::{ }; use crate::coconut::utils::scalar_serde_helper; use crate::error::Error; +use bls12_381::G1Projective; use nym_credentials_interface::{ aggregate_signature_shares, hash_to_scalar, prepare_blind_sign, Attribute, Parameters, PrivateAttribute, PublicAttribute, Signature, SignatureShare, VerificationKey, @@ -126,6 +127,16 @@ impl IssuanceBandwidthCredential { )) } + pub fn blind_serial_number_in_g1subgroup(&self) -> G1Projective { + bandwidth_credential_params().gen1() * self.serial_number + } + + pub fn blinded_g1_serial_number_bs58(&self) -> String { + use nym_credentials_interface::Base58; + + self.blind_serial_number_in_g1subgroup().to_bs58() + } + pub fn new_freepass(expiry_date: Option) -> Self { Self::new(FreePassIssuanceData::new(expiry_date)) } @@ -149,6 +160,10 @@ impl IssuanceBandwidthCredential { ] } + pub fn get_bandwidth_attribute(&self) -> String { + self.variant_data.public_value_plain() + } + pub fn prepare_for_signing(&self) -> CredentialSigningData { let params = bandwidth_credential_params(); diff --git a/common/nymcoconut/src/scheme/setup.rs b/common/nymcoconut/src/scheme/setup.rs index 926d8f5ed0..63add88404 100644 --- a/common/nymcoconut/src/scheme/setup.rs +++ b/common/nymcoconut/src/scheme/setup.rs @@ -44,11 +44,11 @@ impl Parameters { }) } - pub(crate) fn gen1(&self) -> &G1Affine { + pub fn gen1(&self) -> &G1Affine { &self.g1 } - pub(crate) fn gen2(&self) -> &G2Affine { + pub fn gen2(&self) -> &G2Affine { &self.g2 } @@ -56,7 +56,7 @@ impl Parameters { &self._g2_prepared_miller } - pub(crate) fn gen_hs(&self) -> &[G1Affine] { + pub fn gen_hs(&self) -> &[G1Affine] { &self.hs } diff --git a/gateway/src/node/client_handling/bandwidth.rs b/gateway/src/node/client_handling/bandwidth.rs index ae8469c504..ce1caed6a7 100644 --- a/gateway/src/node/client_handling/bandwidth.rs +++ b/gateway/src/node/client_handling/bandwidth.rs @@ -16,13 +16,13 @@ pub enum BandwidthError { #[error("the provided free pass has already expired (expiry was on {expiry_date})")] ExpiredFreePass { expiry_date: OffsetDateTime }, - #[error("failed to pass the bandwidth voucher value: {source}")] + #[error("failed to parse the bandwidth voucher value: {source}")] VoucherValueParsingFailure { #[source] source: ParseIntError, }, - #[error("failed to pass the free pass expiry date: {source}")] + #[error("failed to parse the free pass expiry date: {source}")] ExpiryDateParsingFailure { #[source] source: ParseIntError,