expose upgrade mode information in authenticator responses

This commit is contained in:
Jędrzej Stuczyński
2025-10-27 15:55:12 +00:00
parent 410dd6f725
commit 17894e5f8b
6 changed files with 221 additions and 15 deletions
+21 -2
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::traits::{
Id, PendingRegistrationResponse, RegisteredResponse, RemainingBandwidthResponse,
TopUpBandwidthResponse,
CurrentUpgradeModeStatus, Id, PendingRegistrationResponse, RegisteredResponse,
RemainingBandwidthResponse, TopUpBandwidthResponse, UpgradeModeStatus,
};
use crate::{v2, v3, v4, v5, v6};
@@ -15,6 +15,25 @@ pub enum AuthenticatorResponse {
TopUpBandwidth(Box<dyn TopUpBandwidthResponse + Send + Sync + 'static>),
}
impl UpgradeModeStatus for AuthenticatorResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
match self {
AuthenticatorResponse::PendingRegistration(pending_registration_response) => {
pending_registration_response.upgrade_mode_status()
}
AuthenticatorResponse::Registered(registered_response) => {
registered_response.upgrade_mode_status()
}
AuthenticatorResponse::RemainingBandwidth(remaining_bandwidth_response) => {
remaining_bandwidth_response.upgrade_mode_status()
}
AuthenticatorResponse::TopUpBandwidth(top_up_bandwidth_response) => {
top_up_bandwidth_response.upgrade_mode_status()
}
}
}
}
impl Id for AuthenticatorResponse {
fn id(&self) -> u64 {
match self {
+157 -4
View File
@@ -14,6 +14,24 @@ use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
use tracing::error;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
pub enum CurrentUpgradeModeStatus {
Enabled,
Disabled,
// everything pre-v6
Unknown,
}
impl From<bool> for CurrentUpgradeModeStatus {
fn from(value: bool) -> Self {
if value {
CurrentUpgradeModeStatus::Enabled
} else {
CurrentUpgradeModeStatus::Disabled
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct BandwidthClaim {
pub credential: BandwidthCredential,
@@ -136,6 +154,141 @@ impl Versionable for v6::topup::TopUpMessage {
}
}
pub trait UpgradeModeStatus {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus;
}
impl UpgradeModeStatus for v1::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v1::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v1::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v2::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v2::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v2::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v3::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v3::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v3::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v3::response::TopUpBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v4::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v4::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v4::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v4::response::TopUpBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v5::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v5::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v5::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v5::response::TopUpBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
CurrentUpgradeModeStatus::Unknown
}
}
impl UpgradeModeStatus for v6::response::PendingRegistrationResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
self.upgrade_mode_enabled.into()
}
}
impl UpgradeModeStatus for v6::response::RegisteredResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
self.upgrade_mode_enabled.into()
}
}
impl UpgradeModeStatus for v6::response::RemainingBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
self.upgrade_mode_enabled.into()
}
}
impl UpgradeModeStatus for v6::response::TopUpBandwidthResponse {
fn upgrade_mode_status(&self) -> CurrentUpgradeModeStatus {
self.upgrade_mode_enabled.into()
}
}
pub trait InitMessage: Versionable + fmt::Debug {
fn pub_key(&self) -> PeerPublicKey;
}
@@ -565,7 +718,7 @@ impl Id for v6::response::TopUpBandwidthResponse {
}
}
pub trait PendingRegistrationResponse: Id + fmt::Debug {
pub trait PendingRegistrationResponse: Id + UpgradeModeStatus + fmt::Debug {
fn nonce(&self) -> u64;
fn verify(&self, gateway_key: &x25519::PrivateKey) -> Result<(), Error>;
fn pub_key(&self) -> PeerPublicKey;
@@ -748,7 +901,7 @@ impl PendingRegistrationResponse for v6::response::PendingRegistrationResponse {
}
}
pub trait RegisteredResponse: Id + fmt::Debug {
pub trait RegisteredResponse: Id + UpgradeModeStatus + fmt::Debug {
fn private_ips(&self) -> IpPair;
fn pub_key(&self) -> PeerPublicKey;
fn wg_port(&self) -> u16;
@@ -824,7 +977,7 @@ impl RegisteredResponse for v6::response::RegisteredResponse {
}
}
pub trait RemainingBandwidthResponse: Id + fmt::Debug {
pub trait RemainingBandwidthResponse: Id + UpgradeModeStatus + fmt::Debug {
fn available_bandwidth(&self) -> Option<i64>;
}
@@ -858,7 +1011,7 @@ impl RemainingBandwidthResponse for v6::response::RemainingBandwidthResponse {
}
}
pub trait TopUpBandwidthResponse: Id + fmt::Debug {
pub trait TopUpBandwidthResponse: Id + UpgradeModeStatus + fmt::Debug {
fn available_bandwidth(&self) -> i64;
}
+2 -2
View File
@@ -22,7 +22,7 @@ pub enum AuthenticatorVersion {
/// introduced in dorina-patched release (1.6.1)
V5,
/// introduced in yet to be named release, currently aiming for Kase (1.21.0)
/// introduced in yet to be named release, currently aiming for Leerdammer (1.22.0)
V6,
/// an unknown, future, variant that can be present if running outdated software
@@ -42,7 +42,7 @@ impl AuthenticatorVersion {
AuthenticatorVersion::V3 => semver::Version::new(1, 1, 10),
AuthenticatorVersion::V4 => semver::Version::new(1, 2, 0),
AuthenticatorVersion::V5 => semver::Version::new(1, 6, 1),
AuthenticatorVersion::V6 => semver::Version::new(1, 21, 0),
AuthenticatorVersion::V6 => semver::Version::new(1, 22, 0),
AuthenticatorVersion::UNKNOWN => semver::Version::new(0, 0, 0),
}
}
@@ -5,6 +5,8 @@ use nym_credentials_interface::CredentialSpendingData;
#[cfg(feature = "testing")]
use super::super::v0 as previous;
#[cfg(feature = "testing")]
use crate::{Request, Response, v0};
use super::{
QueryType, VERSION, VersionedRequest, VersionedResponse,
@@ -14,7 +16,6 @@ use super::{
topup_bandwidth::{request::InnerTopUpRequest, response::InnerTopUpResponse},
};
use crate::models::{Construct, Extract, Version, error::Error};
use crate::{Request, Response, v0};
#[derive(Debug, Clone, PartialEq)]
pub enum RequestData {
+23 -6
View File
@@ -12,6 +12,7 @@ use std::time::Duration;
use tracing::{debug, error, trace};
use crate::mixnet_listener::{MixnetMessageBroadcastReceiver, MixnetMessageInputSender};
use nym_authenticator_requests::traits::UpgradeModeStatus;
use nym_authenticator_requests::{
AuthenticatorVersion, client_message::ClientMessage, response::AuthenticatorResponse,
traits::Id, v2, v3, v4, v5, v6,
@@ -24,9 +25,11 @@ use nym_wireguard_types::PeerPublicKey;
mod error;
mod helpers;
mod mixnet_listener;
pub mod types;
pub use crate::error::{Error, Result};
pub use crate::mixnet_listener::{AuthClientMixnetListener, AuthClientMixnetListenerHandle};
use crate::types::{AvailableBandwidthClientResponse, TopUpClientResponse};
pub struct AuthenticatorClient {
mixnet_listener: MixnetMessageBroadcastReceiver,
@@ -299,7 +302,7 @@ impl AuthenticatorClient {
Ok(gateway_data)
}
pub async fn query_bandwidth(&mut self) -> Result<Option<i64>> {
pub async fn query_bandwidth(&mut self) -> Result<AvailableBandwidthClientResponse> {
let pub_key = self.peer_public_key();
let version = self.auth_version;
@@ -316,6 +319,7 @@ impl AuthenticatorClient {
}
};
let response = self.send_and_wait_for_response(&query_message).await?;
let current_upgrade_mode_status = response.upgrade_mode_status();
let available_bandwidth = match response {
AuthenticatorResponse::RemainingBandwidth(remaining_bandwidth_response) => {
@@ -324,7 +328,10 @@ impl AuthenticatorClient {
{
available_bandwidth
} else {
return Ok(None);
return Ok(AvailableBandwidthClientResponse {
available_bandwidth_bytes: None,
current_upgrade_mode_status,
});
}
}
_ => return Err(Error::InvalidGatewayAuthResponse),
@@ -345,10 +352,16 @@ impl AuthenticatorClient {
"Remaining bandwidth is under 1 MB. The wireguard mode will get suspended after that until tomorrow, UTC time. The client might shutdown with timeout soon"
);
}
Ok(Some(available_bandwidth))
Ok(AvailableBandwidthClientResponse {
available_bandwidth_bytes: None,
current_upgrade_mode_status,
})
}
pub async fn top_up(&mut self, credential: CredentialSpendingData) -> Result<i64> {
pub async fn top_up(
&mut self,
credential: CredentialSpendingData,
) -> Result<TopUpClientResponse> {
let pub_key = self.peer_public_key();
let top_up_message = match self.auth_version {
@@ -375,14 +388,18 @@ impl AuthenticatorClient {
}
};
let response = self.send_and_wait_for_response(&top_up_message).await?;
let current_upgrade_mode_status = response.upgrade_mode_status();
let remaining_bandwidth = match response {
let remaining_bandwidth_bytes = match response {
AuthenticatorResponse::TopUpBandwidth(top_up_bandwidth_response) => {
top_up_bandwidth_response.available_bandwidth()
}
_ => return Err(Error::InvalidGatewayAuthResponse),
};
Ok(remaining_bandwidth)
Ok(TopUpClientResponse {
remaining_bandwidth_bytes,
current_upgrade_mode_status,
})
}
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use nym_authenticator_requests::traits::CurrentUpgradeModeStatus;
#[derive(Debug, Clone, Copy)]
pub struct TopUpClientResponse {
pub remaining_bandwidth_bytes: i64,
pub current_upgrade_mode_status: CurrentUpgradeModeStatus,
}
#[derive(Debug, Clone, Copy)]
pub struct AvailableBandwidthClientResponse {
pub available_bandwidth_bytes: Option<i64>,
pub current_upgrade_mode_status: CurrentUpgradeModeStatus,
}