additional gateway logs
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user