additional gateway logs

This commit is contained in:
Jędrzej Stuczyński
2024-02-20 11:03:44 +00:00
parent f96f74f2f1
commit cae97663c1
6 changed files with 48 additions and 5 deletions
@@ -14,7 +14,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub const MAX_FREE_PASS_VALIDITY: Duration = Duration::WEEK; // 1 week
#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
pub struct FreePassIssuedData {
/// the plain validity value of this credential expressed as unix timestamp
#[zeroize(skip)]
@@ -20,7 +20,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub const CURRENT_SERIALIZATION_REVISION: u8 = 1;
#[derive(Zeroize, Serialize, Deserialize)]
#[derive(Debug, Zeroize, Serialize, Deserialize)]
pub enum BandwidthCredentialIssuedDataVariant {
Voucher(BandwidthVoucherIssuedData),
FreePass(FreePassIssuedData),
@@ -13,7 +13,7 @@ use nym_validator_client::nyxd::{Coin, Hash};
use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
pub struct BandwidthVoucherIssuedData {
/// the plain value (e.g., bandwidth) encoded in this voucher
// note: for legacy reasons we're only using the value of the coin and ignoring the denom
@@ -36,6 +36,7 @@ pub enum BandwidthError {
},
}
#[derive(Debug, Copy, Clone)]
pub struct Bandwidth {
value: u64,
}
@@ -21,7 +21,7 @@ use futures::{
};
use log::*;
use nym_credentials::coconut::bandwidth::{bandwidth_credential_params, CredentialType};
use nym_credentials_interface::CoconutError;
use nym_credentials_interface::{Base58, CoconutError};
use nym_gateway_requests::models::CredentialSpendingRequest;
use nym_gateway_requests::{
iv::{IVConversionError, IV},
@@ -227,15 +227,23 @@ where
) -> Result<ServerResponse, RequestHandlingError> {
// check if the credential hasn't been spent before
let serial_number = credential.data.blinded_serial_number();
trace!("processing credential {}", serial_number.to_bs58());
let already_spent = self
.inner
.storage
.contains_credential(&serial_number)
.await?;
if already_spent {
trace!("the credential has already been spent before");
return Err(RequestHandlingError::BandwidthCredentialAlreadySpent);
}
trace!(
"attempting to obtain aggregate verification key for epoch {}",
credential.data.epoch_id
);
let aggregated_verification_key = self
.inner
.coconut_verifier
@@ -243,26 +251,32 @@ where
.await?;
if !credential.data.validate_type_attribute() {
trace!("mismatch in the type attribute");
return Err(RequestHandlingError::InvalidTypeAttribute);
}
let Some(bandwidth_attribute) = credential.data.get_bandwidth_attribute() else {
trace!("missing bandwidth attribute");
return Err(RequestHandlingError::MissingBandwidthAttribute);
};
// this will extract token amounts out of bandwidth vouchers and validate expiry of free passes
let bandwidth = Bandwidth::try_from_raw_value(bandwidth_attribute, credential.data.typ)?;
trace!("embedded bandwidth: {bandwidth:?}");
// locally verify the credential
let params = bandwidth_credential_params();
if !credential.data.verify(params, &aggregated_verification_key) {
trace!("the credential did not verify correctly");
return Err(RequestHandlingError::InvalidBandwidthCredential(
String::from("credential failed to verify on gateway"),
String::from("local credential verification has failed"),
));
}
let was_freepass = match credential.data.typ {
CredentialType::Voucher => {
trace!("the credential is a bandwidth voucher. attempting to release the funds");
let api_clients = self
.inner
.coconut_verifier
@@ -291,11 +305,13 @@ where
// mark the credential as spent
// TODO: technically this should be done under a storage transaction so that if we experience any
// failures later on, it'd get reverted
trace!("storing serial number information");
self.inner
.storage
.insert_spent_credential(serial_number, was_freepass, self.client.address)
.await?;
trace!("increasing client bandwidth");
self.increase_bandwidth(bandwidth).await?;
let available_total = self.get_available_bandwidth().await?;
@@ -307,6 +323,8 @@ where
enc_credential: Vec<u8>,
iv: Vec<u8>,
) -> Result<ServerResponse, RequestHandlingError> {
debug!("handling v1 bandwidth request");
let iv = IV::try_from_bytes(&iv)?;
let credential = ClientControlRequest::try_from_enc_coconut_bandwidth_credential_v1(
enc_credential,
@@ -329,6 +347,8 @@ where
enc_credential: Vec<u8>,
iv: Vec<u8>,
) -> Result<ServerResponse, RequestHandlingError> {
debug!("handling v2 bandwidth request");
let iv = IV::try_from_bytes(&iv)?;
let credential = ClientControlRequest::try_from_enc_coconut_bandwidth_credential_v2(
enc_credential,
@@ -342,6 +362,8 @@ where
async fn handle_claim_testnet_bandwidth(
&mut self,
) -> Result<ServerResponse, RequestHandlingError> {
debug!("handling testnet bandwidth request");
if self.inner.only_coconut_credentials {
return Err(RequestHandlingError::OnlyCoconutCredentials);
}
@@ -389,6 +411,7 @@ where
///
/// * `bin_msg`: raw message to handle.
async fn handle_binary(&self, bin_msg: Vec<u8>) -> Message {
trace!("binary request");
// this function decrypts the request and checks the MAC
match BinaryRequest::try_from_encrypted_tagged_bytes(bin_msg, &self.client.shared_keys) {
Err(e) => {
@@ -413,6 +436,7 @@ where
///
/// * `raw_request`: raw message to handle.
async fn handle_text(&mut self, raw_request: String) -> Message {
trace!("text request");
match ClientControlRequest::try_from(raw_request) {
Err(e) => RequestHandlingError::InvalidTextRequest(e).into_error_message(),
Ok(request) => match request {
@@ -465,6 +489,12 @@ where
///
/// * `raw_request`: raw received websocket message.
async fn handle_request(&mut self, raw_request: Message) -> Option<Message> {
// TODO: this should be added via tracing
debug!(
"handling request from {}",
self.client.address.as_base58_string()
);
// apparently tungstenite auto-handles ping/pong/close messages so for now let's ignore
// them and let's test that claim. If that's not the case, just copy code from
// desktop nym-client websocket as I've manually handled everything there
@@ -112,10 +112,15 @@ impl CoconutVerifier {
// the key was already in the map
if let Ok(mapped) = RwLockReadGuard::try_map(guard, |clients| clients.get(&epoch_id)) {
trace!("we already had cached api clients for epoch {epoch_id}");
return Ok(mapped);
}
let api_clients = self.query_api_clients(epoch_id).await?;
trace!(
"obtained {} api clients for epoch {epoch_id} from the contract",
api_clients.len()
);
// EDGE CASE:
// if this epoch is from the past, we can't query for its threshold
@@ -131,6 +136,7 @@ impl CoconutVerifier {
let mut guard = self.api_clients.write().await;
guard.insert(epoch_id, api_clients);
let guard = guard.downgrade();
trace!("stored api clients for epoch {epoch_id}");
// SAFETY:
// we just inserted the entry into the map while NEVER dropping the lock (only downgraded it)
@@ -149,10 +155,15 @@ impl CoconutVerifier {
// the key was already in the map
if let Ok(mapped) = RwLockReadGuard::try_map(guard, |keys| keys.get(&epoch_id)) {
trace!("we already had cached verification key for epoch {epoch_id}");
return Ok(mapped);
}
let api_clients = self.api_clients(epoch_id).await?;
trace!(
"attempting to obtain verification key from {} api clients",
api_clients.len()
);
let aggregated_verification_key =
nym_credentials::obtain_aggregate_verification_key(&api_clients)?;
@@ -160,6 +171,7 @@ impl CoconutVerifier {
let mut guard = self.master_keys.write().await;
guard.insert(epoch_id, aggregated_verification_key);
let guard = guard.downgrade();
trace!("stored aggregated verification key for epoch {epoch_id}");
// SAFETY:
// we just inserted the entry into the map while NEVER dropping the lock (only downgraded it)