Files
nym/common/credential-verification/src/lib.rs
T
Jędrzej Stuczyński 5a07b73375 feature: hopefully final steps of the smoosh™️ (#5201)
* removed mnemonic from gateway config struct

scaffolding for common mixnet listener

running verloc unconditionally in a nym-node

remove filtering by mixnode

extracted verloc to separate crate

integrated nym-node-http-server more tightly with the binary

most logic for handling forward packets

running all mixnode-related tasks natively inside nymnode

removed gateway storage trait in favour of the only concrete implementation

most logic for handling final hop packets

using nym-node owned socket listener for gateways

utility for sending plain message through mixnet + gateway fix

using common packet forwarding in both modes

nifying nym-node metrics

reproduce behaviour of the console logger

cleaned up cli args

redesigned gateway tasks startup procedure

removing dead code

scaffolding for old config v6

config migration

implemented MixnetMetricsCleaner

* clippy

* require entry/exit for wireguard

* removed dead code in migration code

* updated config template

* use custom user agent for verloc queries

* fixed premature shutdown of gateway tasks

* hidden nym-api flag to allow illegal node ips

* experiment: final hop handing with wireguard

* added additional startup logs

* typo

* fixed legacy stats endpoint data

* additional logs

* apply review comments

* fixed local testnet manager
2024-12-05 17:21:36 +00:00

142 lines
4.4 KiB
Rust

// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use bandwidth_storage_manager::BandwidthStorageManager;
use ecash::EcashManager;
use nym_credentials::ecash::utils::{cred_exp_date, ecash_today, EcashTime};
use nym_credentials_interface::{Bandwidth, ClientTicket, TicketType};
use nym_gateway_requests::models::CredentialSpendingRequest;
use std::sync::Arc;
use time::{Date, OffsetDateTime};
use tracing::*;
pub use client_bandwidth::*;
pub use error::*;
pub mod bandwidth_storage_manager;
mod client_bandwidth;
pub mod ecash;
pub mod error;
pub struct CredentialVerifier {
credential: CredentialSpendingRequest,
ecash_verifier: Arc<EcashManager>,
bandwidth_storage_manager: BandwidthStorageManager,
}
impl CredentialVerifier {
pub fn new(
credential: CredentialSpendingRequest,
ecash_verifier: Arc<EcashManager>,
bandwidth_storage_manager: BandwidthStorageManager,
) -> Self {
CredentialVerifier {
credential,
ecash_verifier,
bandwidth_storage_manager,
}
}
fn check_credential_spending_date(&self, today: Date) -> Result<()> {
let proposed = self.credential.data.spend_date;
trace!("checking ticket spending date...");
if today != proposed {
trace!("invalid credential spending date. received {proposed}");
return Err(Error::InvalidCredentialSpendingDate {
got: proposed,
expected: today,
});
}
Ok(())
}
async fn check_local_db_for_double_spending(&self, serial_number: &[u8]) -> Result<()> {
trace!("checking local db for double spending...");
let spent = self
.bandwidth_storage_manager
.storage
.contains_ticket(serial_number)
.await?;
if spent {
trace!("the credential has already been spent before at this gateway");
return Err(Error::BandwidthCredentialAlreadySpent);
}
Ok(())
}
async fn cryptographically_verify_ticket(&self) -> Result<()> {
trace!("attempting to perform ticket verification...");
let aggregated_verification_key = self
.ecash_verifier
.verification_key(self.credential.data.epoch_id)
.await?;
self.ecash_verifier
.check_payment(&self.credential.data, &aggregated_verification_key)
.await?;
Ok(())
}
async fn store_received_ticket(&self, received_at: OffsetDateTime) -> Result<i64> {
trace!("storing received ticket");
let ticket_id = self
.bandwidth_storage_manager
.storage
.insert_received_ticket(
self.bandwidth_storage_manager.client_id,
received_at,
self.credential.encoded_serial_number(),
self.credential.to_bytes(),
)
.await?;
Ok(ticket_id)
}
fn async_verify_ticket(&self, ticket_id: i64) {
let client_ticket = ClientTicket::new(self.credential.data.clone(), ticket_id);
self.ecash_verifier.async_verify(client_ticket);
}
pub async fn verify(&mut self) -> Result<i64> {
let received_at = OffsetDateTime::now_utc();
let spend_date = ecash_today();
// check if the credential hasn't been spent before
let serial_number = self.credential.data.encoded_serial_number();
let credential_type = TicketType::try_from_encoded(self.credential.data.payment.t_type)?;
if self.credential.data.payment.spend_value != 1 {
return Err(Error::MultipleTickets);
}
self.check_credential_spending_date(spend_date.ecash_date())?;
self.check_local_db_for_double_spending(&serial_number)
.await?;
// TODO: do we HAVE TO do it?
self.cryptographically_verify_ticket().await?;
let ticket_id = self.store_received_ticket(received_at).await?;
self.async_verify_ticket(ticket_id);
// TODO: double storing?
// self.store_spent_credential(serial_number_bs58).await?;
let bandwidth = Bandwidth::ticket_amount(credential_type.into());
self.bandwidth_storage_manager
.increase_bandwidth(bandwidth, cred_exp_date())
.await?;
Ok(self
.bandwidth_storage_manager
.client_bandwidth
.available()
.await)
}
}