Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.lock

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

5 changes: 4 additions & 1 deletion common/client-core/gateways-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rust-version.workspace = true
[dependencies]
async-trait.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
thiserror.workspace = true
time.workspace = true
tokio = { workspace = true, features = ["sync"] }
Expand All @@ -20,10 +21,11 @@ zeroize = { workspace = true, features = ["zeroize_derive"] }
nym-crypto = { path = "../../crypto", features = ["asymmetric"] }
nym-gateway-requests = { path = "../../gateway-requests" }
nym-gateway-client = { path = "../../client-libs/gateway-client" }
nym-topology = { path = "../../topology", features = ["persistence"] }

[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"]
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time", "json"]
optional = true

[build-dependencies]
Expand All @@ -34,6 +36,7 @@ sqlx = { workspace = true, features = [
"sqlite",
"macros",
"migrate",
"json",
] }

[features]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2025 - Nym Technologies SA <[email protected]>
* SPDX-License-Identifier: Apache-2.0
*/

CREATE TABLE remote_gateway_details_temp
(
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
derived_aes256_gcm_siv_key BLOB NOT NULL,
gateway_details TEXT NOT NULL CHECK (json_valid(gateway_details)),
expiration_timestamp DATETIME NOT NULL
);

-- keep none, the gateways listener URL does not contain the gateway details information
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then we're losing our shared keys

-- INSERT INTO remote_gateway_details_temp SELECT gateway_id_bs58, derived_aes256_gcm_siv_key, gateway_listener, NULL, datetime(0, 'unixepoch') FROM remote_gateway_details WHERE derived_aes256_gcm_siv_key IS NOT NULL;

DROP TABLE remote_gateway_details;
ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details;

-- delete registrations with no key
DELETE FROM registered_gateway WHERE gateway_id_bs58 NOT IN ( SELECT gateway_id_bs58 FROM remote_gateway_details);
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,16 @@ impl StorageManager {
&self,
remote: &RawRemoteGatewayDetails,
) -> Result<(), sqlx::Error> {
let details =
serde_json::to_string(&remote.published_data.gateway_details).expect("AHHHHHHHHH");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems something is missing here : )

sqlx::query!(
r#"
INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes256_gcm_siv_key, gateway_listener, fallback_listener, expiration_timestamp)
VALUES (?, ?, ?, ?, ?)
INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes256_gcm_siv_key, gateway_details, expiration_timestamp)
VALUES (?, ?, ?, ?)
"#,
remote.gateway_id_bs58,
remote.derived_aes256_gcm_siv_key,
remote.published_data.gateway_listener,
remote.published_data.fallback_listener,
details,
remote.published_data.expiration_timestamp
)
.execute(&self.connection_pool)
Expand All @@ -177,12 +178,12 @@ impl StorageManager {
gateway_id_bs58: &str,
published_data: &RawGatewayPublishedData,
) -> Result<(), sqlx::Error> {
let details = serde_json::to_string(&published_data.gateway_details).expect("AHHHHHHHHH");
sqlx::query!(
r#"
UPDATE remote_gateway_details SET gateway_listener = ?, fallback_listener = ?, expiration_timestamp = ? WHERE gateway_id_bs58 = ?
UPDATE remote_gateway_details SET gateway_details = ?, expiration_timestamp = ? WHERE gateway_id_bs58 = ?
"#,
published_data.gateway_listener,
published_data.fallback_listener,
details,
published_data.expiration_timestamp,
gateway_id_bs58
)
Expand Down
21 changes: 5 additions & 16 deletions common/client-core/gateways-storage/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
use nym_gateway_requests::shared_key::SharedKeyConversionError;
use serde_json::Error as JsonError;
use thiserror::Error;

#[derive(Debug, Error)]
Expand All @@ -29,23 +30,11 @@ pub enum BadGateway {
#[error("could not find any valid shared keys for gateway {gateway_id}")]
MissingSharedKey { gateway_id: String },

#[error(
"the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
)]
MalformedListener {
gateway_id: String,

raw_listener: String,

#[source]
source: url::ParseError,
},

#[error("the listening address ({raw_listener}) is malformed: {source}")]
MalformedListenerNoId {
raw_listener: String,
#[error("the listening address ({raw_details}) is malformed: {source}")]
MalformedDetailsNoId {
raw_details: String,

#[source]
source: url::ParseError,
source: JsonError,
},
}
44 changes: 15 additions & 29 deletions common/client-core/gateways-storage/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@

use crate::BadGateway;
use nym_crypto::asymmetric::ed25519;
use nym_gateway_client::client::GatewayListeners;
use nym_gateway_requests::shared_key::SharedSymmetricKey;
use nym_topology::EntryDetails;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use std::sync::Arc;
use time::Duration;
use time::OffsetDateTime;
use url::Url;
use zeroize::{Zeroize, ZeroizeOnDrop};

pub const REMOTE_GATEWAY_TYPE: &str = "remote";
Expand Down Expand Up @@ -172,14 +171,14 @@ pub struct RegisteredGateway {

#[derive(Debug, Clone)]
pub struct GatewayPublishedData {
pub listeners: GatewayListeners,
pub details: EntryDetails,
pub expiration_timestamp: OffsetDateTime,
}

impl GatewayPublishedData {
pub fn new(listeners: GatewayListeners) -> GatewayPublishedData {
pub fn new(details: EntryDetails) -> GatewayPublishedData {
GatewayPublishedData {
listeners,
details,
expiration_timestamp: OffsetDateTime::now_utc() + GATEWAY_DETAILS_TTL,
}
}
Expand All @@ -188,16 +187,16 @@ impl GatewayPublishedData {
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct RawGatewayPublishedData {
pub gateway_listener: String,
pub fallback_listener: Option<String>,
#[cfg_attr(feature = "sqlx", sqlx(json))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does json actually work with sqlx + sqlite? i.e. have you run it before? I remember I had problems with that combination in the past and json was only supported with postgres. but that was in an older version so it might have changed

pub gateway_details: EntryDetails,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, for the purposes of the database schema, it'd make more sense to redefine that type, even if it would duplicate all the data. The reason is that EntryDetails is an external type that can change at any time and then the database would suddenly break due to changes in serialisation.

pub expiration_timestamp: OffsetDateTime,
}

impl<'a> From<&'a GatewayPublishedData> for RawGatewayPublishedData {
fn from(value: &'a GatewayPublishedData) -> Self {
Self {
gateway_listener: value.listeners.primary.to_string(),
fallback_listener: value.listeners.fallback.as_ref().map(|uri| uri.to_string()),
// fallback_listener: value.listeners.fallback.as_ref().map(|uri| uri.to_string()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

gateway_details: value.details.clone(),
expiration_timestamp: value.expiration_timestamp,
}
}
Expand All @@ -207,28 +206,15 @@ impl TryFrom<RawGatewayPublishedData> for GatewayPublishedData {
type Error = BadGateway;

fn try_from(value: RawGatewayPublishedData) -> Result<Self, Self::Error> {
let gateway_listener: Url = Url::parse(&value.gateway_listener).map_err(|source| {
BadGateway::MalformedListenerNoId {
raw_listener: value.gateway_listener.clone(),
source,
}
})?;
let fallback_listener = value
.fallback_listener
.as_ref()
.map(|uri| {
Url::parse(uri).map_err(|source| BadGateway::MalformedListenerNoId {
raw_listener: uri.to_owned(),
source,
})
})
.transpose()?;
// let details = serde_json::from_str(&value.gateway_listener).map_err(|source| {
// BadGateway::MalformedDetailsNoId {
// raw_details: value.gateway_listener.clone(),
// source,
// }
// })?;

Ok(GatewayPublishedData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this now looks to be infallible, so change the TryFrom into a normal From instead

listeners: GatewayListeners {
primary: gateway_listener,
fallback: fallback_listener,
},
details: value.gateway_details,
expiration_timestamp: value.expiration_timestamp,
})
}
Expand Down
4 changes: 1 addition & 3 deletions common/client-core/src/cli_helpers/client_add_gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ where
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(common_args.latency_based_selection),
common_args.force_tls_gateway,
false,
);
tracing::debug!("Gateway selection specification: {selection_spec:?}");

Expand Down Expand Up @@ -168,7 +167,6 @@ where
identity: gateway_details.gateway_id,
active: common_args.set_active,
typ: gateway_registration.details.typ().to_string(),
endpoint: Some(gateway_details.published_data.listeners.primary.clone()),
fallback_endpoint: gateway_details.published_data.listeners.fallback.clone(),
endpoint: Some(gateway_details.published_data.details.clone()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a nit, but I think it'd make more sense to rename that field. it's no longer just an endpoint

})
}
1 change: 0 additions & 1 deletion common/client-core/src/cli_helpers/client_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ where
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(common_args.latency_based_selection),
common_args.force_tls_gateway,
false,
);
tracing::debug!("Gateway selection specification: {selection_spec:?}");

Expand Down
4 changes: 1 addition & 3 deletions common/client-core/src/cli_helpers/client_list_gateways.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,14 @@ where
identity: remote_details.gateway_id,
active: active_gateway == Some(remote_details.gateway_id),
typ: GatewayType::Remote.to_string(),
endpoint: Some(remote_details.published_data.listeners.primary.clone()),
fallback_endpoint: remote_details.published_data.listeners.fallback.clone(),
endpoint: Some(remote_details.published_data.details.clone()),
}),
GatewayDetails::Custom(_) => info.push(GatewayInfo {
registration: gateway.registration_timestamp,
identity: gateway.details.gateway_id(),
active: active_gateway == Some(gateway.details.gateway_id()),
typ: gateway.details.typ().to_string(),
endpoint: None,
fallback_endpoint: None,
}),
};
}
Expand Down
8 changes: 2 additions & 6 deletions common/client-core/src/cli_helpers/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

use nym_crypto::asymmetric::ed25519;
use nym_topology::EntryDetails;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use time::OffsetDateTime;
use url::Url;

#[derive(Serialize, Deserialize)]
pub struct GatewayInfo {
Expand All @@ -14,8 +14,7 @@ pub struct GatewayInfo {
pub active: bool,

pub typ: String,
pub endpoint: Option<Url>,
pub fallback_endpoint: Option<Url>,
pub endpoint: Option<EntryDetails>,
}

impl Display for GatewayInfo {
Expand All @@ -31,9 +30,6 @@ impl Display for GatewayInfo {
if let Some(endpoint) = &self.endpoint {
write!(f, " endpoint: {endpoint}")?;
}
if let Some(fallback_endpoint) = &self.fallback_endpoint {
write!(f, " fallback: {fallback_endpoint}")?;
}
Ok(())
}
}
2 changes: 1 addition & 1 deletion common/client-core/src/client/base_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ where
shutdown_tracker.clone_shutdown_token(),
)
} else {
let cfg = GatewayConfig::new(details.gateway_id, details.published_data.listeners);
let cfg = GatewayConfig::new(details.gateway_id, details.published_data.details);
GatewayClient::new(
GatewayClientConfig::new_default()
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
Expand Down
11 changes: 2 additions & 9 deletions common/client-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,8 @@ pub enum ClientCoreError {
#[error("no gateway with id: {0}")]
NoGatewayWithId(String),

#[error("Invalid URL: {0}")]
InvalidUrl(String),

#[error("node doesn't advertise ip addresses : {0}")]
MissingIpAddress(String),

#[cfg(not(target_arch = "wasm32"))]
#[error("resolution failed: {0}")]
ResolutionFailed(#[from] nym_http_api_client::ResolveError),
#[error("Invalid Endpoint: {0}")]
InvalidEndpoint(String),

#[error("no gateways on network")]
NoGatewaysOnNetwork,
Expand Down
Loading
Loading