Skip to content

Commit

Permalink
add ticket report
Browse files Browse the repository at this point in the history
  • Loading branch information
simonwicky committed Nov 12, 2024
1 parent 26f55a3 commit b7463e5
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion common/client-core/src/client/base_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ where
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter,
stats_reporter: ClientStatsSender,
shutdown: TaskClient,
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
where
Expand All @@ -373,7 +374,12 @@ where

let mut gateway_client =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
existing_client.upgrade(
packet_router,
bandwidth_controller,
stats_reporter,
shutdown,
)
} else {
let cfg = GatewayConfig::new(
details.gateway_id,
Expand All @@ -394,6 +400,7 @@ where
Some(details.shared_key),
packet_router,
bandwidth_controller,
stats_reporter,
shutdown,
)
};
Expand Down Expand Up @@ -446,13 +453,15 @@ where
Ok(gateway_client)
}

#[allow(clippy::too_many_arguments)]
async fn setup_gateway_transceiver(
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
config: &Config,
initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter,
stats_reporter: ClientStatsSender,
mut shutdown: TaskClient,
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
where
Expand Down Expand Up @@ -483,6 +492,7 @@ where
bandwidth_controller,
details_store,
packet_router,
stats_reporter,
shutdown,
)
.await?;
Expand Down Expand Up @@ -771,6 +781,7 @@ where
bandwidth_controller,
&details_store,
gateway_packet_router,
stats_reporter.clone(),
shutdown.fork("gateway_transceiver"),
)
.await?;
Expand Down
1 change: 1 addition & 0 deletions common/client-libs/gateway-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ nym-crypto = { path = "../../crypto" }
nym-gateway-requests = { path = "../../gateway-requests" }
nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" }
nym-statistics-common = { path = "../../statistics" }
nym-pemstore = { path = "../../pemstore" }
nym-validator-client = { path = "../validator-client", default-features = false }
nym-task = { path = "../../task" }
Expand Down
23 changes: 21 additions & 2 deletions common/client-libs/gateway-client/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use nym_gateway_requests::{
CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
};
use nym_sphinx::forwarding::packet::MixPacket;
use nym_statistics_common::clients::credential::CredentialStatsEvent;
use nym_statistics_common::clients::ClientStatsSender;
use nym_task::TaskClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use rand::rngs::OsRng;
Expand Down Expand Up @@ -94,6 +96,7 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
connection: SocketState,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,

// currently unused (but populated)
negotiated_protocol: Option<u8>,
Expand All @@ -103,6 +106,7 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
}

impl<C, St> GatewayClient<C, St> {
#[allow(clippy::too_many_arguments)]
pub fn new(
cfg: GatewayClientConfig,
gateway_config: GatewayConfig,
Expand All @@ -111,6 +115,7 @@ impl<C, St> GatewayClient<C, St> {
shared_key: Option<Arc<SharedGatewayKey>>,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,
task_client: TaskClient,
) -> Self {
GatewayClient {
Expand All @@ -124,6 +129,7 @@ impl<C, St> GatewayClient<C, St> {
connection: SocketState::NotConnected,
packet_router,
bandwidth_controller,
stats_reporter,
negotiated_protocol: None,
task_client,
}
Expand Down Expand Up @@ -714,6 +720,7 @@ impl<C, St> GatewayClient<C, St> {
{
// TODO: make it configurable
const TICKETS_TO_SPEND: u32 = 1;
const MIXNET_TICKET: TicketType = TicketType::V1MixnetEntry;

if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
Expand Down Expand Up @@ -750,14 +757,23 @@ impl<C, St> GatewayClient<C, St> {
let prepared_credential = self
.unchecked_bandwidth_controller()
.prepare_ecash_ticket(
TicketType::V1MixnetEntry,
MIXNET_TICKET,
self.gateway_identity.to_bytes(),
TICKETS_TO_SPEND,
)
.await?;

match self.claim_ecash_bandwidth(prepared_credential.data).await {
Ok(_) => Ok(()),
Ok(_) => {
self.stats_reporter.report(
CredentialStatsEvent::TicketSpent {
typ: MIXNET_TICKET,
amount: TICKETS_TO_SPEND,
}
.into(),
);
Ok(())
}
Err(err) => {
error!("failed to claim ecash bandwidth with the gateway...: {err}");
if err.is_ticket_replay() {
Expand Down Expand Up @@ -1030,6 +1046,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
connection: SocketState::NotConnected,
packet_router,
bandwidth_controller: None,
stats_reporter: ClientStatsSender::new(None),
negotiated_protocol: None,
task_client,
}
Expand All @@ -1039,6 +1056,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
self,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,
task_client: TaskClient,
) -> GatewayClient<C, St> {
// invariants that can't be broken
Expand All @@ -1058,6 +1076,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
connection: self.connection,
packet_router,
bandwidth_controller,
stats_reporter,
negotiated_protocol: self.negotiated_protocol,
task_client,
}
Expand Down
52 changes: 52 additions & 0 deletions common/statistics/src/clients/credential.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2024 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: Apache-2.0

use super::ClientStatsEvents;

use nym_credentials_interface::TicketType;
use serde::{Deserialize, Serialize};

#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
pub(crate) struct CredentialStats {
mixnet_entry_spent: u32,
vpn_entry_spent: u32,
mixnet_exit_spent: u32,
vpn_exit_spent: u32,
}

/// Event space for Nym API statistics tracking
#[derive(Debug)]
pub enum CredentialStatsEvent {
/// ecash ticket was spend
TicketSpent { typ: TicketType, amount: u32 },
}

impl From<CredentialStatsEvent> for ClientStatsEvents {
fn from(event: CredentialStatsEvent) -> ClientStatsEvents {
ClientStatsEvents::Credential(event)
}
}

/// Nym API statistics tracking object
#[derive(Default)]
pub struct CredentialStatsControl {
// Keep track of packet statistics over time
stats: CredentialStats,
}

impl CredentialStatsControl {
pub(crate) fn handle_event(&mut self, event: CredentialStatsEvent) {
match event {
CredentialStatsEvent::TicketSpent { typ, amount } => match typ {
TicketType::V1MixnetEntry => self.stats.mixnet_entry_spent += amount,
TicketType::V1MixnetExit => self.stats.mixnet_exit_spent += amount,
TicketType::V1WireguardEntry => self.stats.vpn_entry_spent += amount,
TicketType::V1WireguardExit => self.stats.vpn_exit_spent += amount,
},
}
}

pub(crate) fn report(&self) -> CredentialStats {
self.stats
}
}
9 changes: 9 additions & 0 deletions common/statistics/src/clients/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub mod nym_api_statistics;
/// Packet count based statistics.
pub mod packet_statistics;

pub mod credential;

/// Channel receiving generic stats events to be used by a statistics aggregator.
pub type ClientStatsReceiver = tokio::sync::mpsc::UnboundedReceiver<ClientStatsEvents>;

Expand Down Expand Up @@ -49,6 +51,8 @@ pub enum ClientStatsEvents {
GatewayConn(gateway_conn_statistics::GatewayStatsEvent),
/// Nym API connection events
NymApi(nym_api_statistics::NymApiStatsEvent),
/// Credential events
Credential(credential::CredentialStatsEvent),
}

/// Controls stats event handling and reporting
Expand All @@ -63,6 +67,7 @@ pub struct ClientStatsController {
packet_stats: packet_statistics::PacketStatisticsControl,
gateway_conn_stats: gateway_conn_statistics::GatewayStatsControl,
nym_api_stats: nym_api_statistics::NymApiStatsControl,
credential_stats: credential::CredentialStatsControl,
}

impl ClientStatsController {
Expand All @@ -76,6 +81,7 @@ impl ClientStatsController {
packet_stats: Default::default(),
gateway_conn_stats: Default::default(),
nym_api_stats: Default::default(),
credential_stats: Default::default(),
}
}
/// Returns a static ClientStatsReport that can be sent somewhere
Expand All @@ -88,6 +94,7 @@ impl ClientStatsController {
packet_stats: self.packet_stats.report(),
gateway_conn_stats: self.gateway_conn_stats.report(),
nym_api_stats: self.nym_api_stats.report(),
credential_stats: self.credential_stats.report(),
}
}

Expand All @@ -97,6 +104,7 @@ impl ClientStatsController {
ClientStatsEvents::PacketStatistics(event) => self.packet_stats.handle_event(event),
ClientStatsEvents::GatewayConn(event) => self.gateway_conn_stats.handle_event(event),
ClientStatsEvents::NymApi(event) => self.nym_api_stats.handle_event(event),
ClientStatsEvents::Credential(event) => self.credential_stats.handle_event(event),
}
}

Expand All @@ -106,6 +114,7 @@ impl ClientStatsController {
pub fn reset(&mut self) {
self.nym_api_stats = Default::default();
self.gateway_conn_stats = Default::default();
self.credential_stats = Default::default();
//no periodic reset for packet stats

self.last_update_time = ClientStatsController::get_update_time();
Expand Down
5 changes: 3 additions & 2 deletions common/statistics/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0

use crate::clients::{
gateway_conn_statistics::GatewayStats, nym_api_statistics::NymApiStats,
packet_statistics::PacketStatistics,
credential::CredentialStats, gateway_conn_statistics::GatewayStats,
nym_api_statistics::NymApiStats, packet_statistics::PacketStatistics,
};

use super::error::StatsError;
Expand All @@ -22,6 +22,7 @@ pub struct ClientStatsReport {
pub(crate) packet_stats: PacketStatistics,
pub(crate) gateway_conn_stats: GatewayStats,
pub(crate) nym_api_stats: NymApiStats,
pub(crate) credential_stats: CredentialStats,
}

impl From<ClientStatsReport> for Vec<u8> {
Expand Down
1 change: 1 addition & 0 deletions nym-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ nym-node-requests = { path = "../nym-node/nym-node-requests" }
nym-types = { path = "../common/types" }
nym-http-api-common = { path = "../common/http-api-common", features = ["utoipa"] }
nym-serde-helpers = { path = "../common/serde-helpers", features = ["date"] }
nym-statistics-common = {path ="../common/statistics" }

[features]
no-reward = []
Expand Down
1 change: 1 addition & 0 deletions nym-api/src/network_monitor/monitor/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ impl PacketSender {
None,
gateway_packet_router,
Some(fresh_gateway_client_data.bandwidth_controller.clone()),
nym_statistics_common::clients::ClientStatsSender::new(None),
task_client,
);

Expand Down

0 comments on commit b7463e5

Please sign in to comment.