[Product data] Data consumption with ecash ticket (#5120)
* add ticket report * fix wasm client
This commit is contained in:
Generated
+3
@@ -4502,6 +4502,7 @@ dependencies = [
|
||||
"nym-pemstore",
|
||||
"nym-serde-helpers",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-topology",
|
||||
"nym-types",
|
||||
@@ -5496,6 +5497,7 @@ dependencies = [
|
||||
"nym-network-defaults",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"rand",
|
||||
@@ -10946,6 +10948,7 @@ dependencies = [
|
||||
"nym-gateway-client",
|
||||
"nym-sphinx",
|
||||
"nym-sphinx-acknowledgements",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-topology",
|
||||
"nym-validator-client",
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -394,6 +400,7 @@ where
|
||||
Some(details.shared_key),
|
||||
packet_router,
|
||||
bandwidth_controller,
|
||||
stats_reporter,
|
||||
shutdown,
|
||||
)
|
||||
};
|
||||
@@ -446,6 +453,7 @@ where
|
||||
Ok(gateway_client)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn setup_gateway_transceiver(
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
config: &Config,
|
||||
@@ -453,6 +461,7 @@ where
|
||||
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
|
||||
@@ -483,6 +492,7 @@ where
|
||||
bandwidth_controller,
|
||||
details_store,
|
||||
packet_router,
|
||||
stats_reporter,
|
||||
shutdown,
|
||||
)
|
||||
.await?;
|
||||
@@ -766,6 +776,7 @@ where
|
||||
bandwidth_controller,
|
||||
&details_store,
|
||||
gateway_packet_router,
|
||||
stats_reporter.clone(),
|
||||
shutdown.fork("gateway_transceiver"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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;
|
||||
@@ -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>,
|
||||
@@ -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,
|
||||
@@ -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 {
|
||||
@@ -124,6 +129,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
connection: SocketState::NotConnected,
|
||||
packet_router,
|
||||
bandwidth_controller,
|
||||
stats_reporter,
|
||||
negotiated_protocol: None,
|
||||
task_client,
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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() {
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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
|
||||
@@ -1058,6 +1076,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
connection: self.connection,
|
||||
packet_router,
|
||||
bandwidth_controller,
|
||||
stats_reporter,
|
||||
negotiated_protocol: self.negotiated_protocol,
|
||||
task_client,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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> {
|
||||
|
||||
@@ -30,6 +30,7 @@ nym-crypto = { path = "../../crypto", features = ["asymmetric", "serde"] }
|
||||
nym-gateway-client = { path = "../../client-libs/gateway-client", default-features = false, features = ["wasm"] }
|
||||
nym-sphinx = { path = "../../nymsphinx" }
|
||||
nym-sphinx-acknowledgements = { path = "../../nymsphinx/acknowledgements", features = ["serde"]}
|
||||
nym-statistics-common = { path = "../../statistics" }
|
||||
nym-task = { path = "../../task" }
|
||||
nym-topology = { path = "../../topology", features = ["serializable", "wasm-serde-types"] }
|
||||
nym-validator-client = { path = "../../client-libs/validator-client", default-features = false }
|
||||
|
||||
@@ -26,6 +26,7 @@ pub use nym_sphinx::{
|
||||
params::PacketType,
|
||||
receiver::ReconstructedMessage,
|
||||
};
|
||||
pub use nym_statistics_common::clients::ClientStatsSender;
|
||||
pub use nym_task;
|
||||
pub use nym_topology::{HardcodedTopologyProvider, MixLayer, NymTopology, TopologyProvider};
|
||||
pub use nym_validator_client::nym_api::Client as ApiClient;
|
||||
|
||||
@@ -119,6 +119,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 = []
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ use wasm_client_core::helpers::{
|
||||
use wasm_client_core::storage::ClientStorage;
|
||||
use wasm_client_core::topology::SerializableNymTopology;
|
||||
use wasm_client_core::{
|
||||
nym_task, BandwidthController, ClientKeys, GatewayClient, GatewayClientConfig, GatewayConfig,
|
||||
IdentityKey, InitialisationResult, NodeIdentity, NymTopology, QueryReqwestRpcNyxdClient,
|
||||
Recipient,
|
||||
nym_task, BandwidthController, ClientKeys, ClientStatsSender, GatewayClient,
|
||||
GatewayClientConfig, GatewayConfig, IdentityKey, InitialisationResult, NodeIdentity,
|
||||
NymTopology, QueryReqwestRpcNyxdClient, Recipient,
|
||||
};
|
||||
use wasm_utils::check_promise_result;
|
||||
use wasm_utils::error::PromisableResult;
|
||||
@@ -194,6 +194,7 @@ impl NymNodeTesterBuilder {
|
||||
existing_client.upgrade(
|
||||
packet_router,
|
||||
self.bandwidth_controller.take(),
|
||||
ClientStatsSender::new(None),
|
||||
gateway_task,
|
||||
)
|
||||
} else {
|
||||
@@ -209,6 +210,7 @@ impl NymNodeTesterBuilder {
|
||||
Some(gateway_info.shared_key),
|
||||
packet_router,
|
||||
self.bandwidth_controller.take(),
|
||||
ClientStatsSender::new(None),
|
||||
gateway_task,
|
||||
)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user