proper type conversions and client compat
This commit is contained in:
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
* 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_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
|
||||
gateway_owner_address TEXT,
|
||||
gateway_listener TEXT NOT NULL,
|
||||
wg_tun_address TEXT
|
||||
);
|
||||
|
||||
INSERT INTO remote_gateway_details_temp SELECT * FROM remote_gateway_details;
|
||||
|
||||
DROP TABLE remote_gateway_details;
|
||||
ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details;
|
||||
@@ -65,7 +65,7 @@ impl GatewayDetails {
|
||||
pub fn new_remote(
|
||||
gateway_id: identity::PublicKey,
|
||||
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||
gateway_owner_address: AccountId,
|
||||
gateway_owner_address: Option<AccountId>,
|
||||
gateway_listener: Url,
|
||||
wg_tun_address: Option<Url>,
|
||||
) -> Self {
|
||||
@@ -170,7 +170,7 @@ pub struct RegisteredGateway {
|
||||
pub struct RawRemoteGatewayDetails {
|
||||
pub gateway_id_bs58: String,
|
||||
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
|
||||
pub gateway_owner_address: String,
|
||||
pub gateway_owner_address: Option<String>,
|
||||
pub gateway_listener: String,
|
||||
pub wg_tun_address: Option<String>,
|
||||
}
|
||||
@@ -195,14 +195,19 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
||||
})?,
|
||||
);
|
||||
|
||||
let gateway_owner_address =
|
||||
AccountId::from_str(&value.gateway_owner_address).map_err(|source| {
|
||||
BadGateway::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: value.gateway_id_bs58.clone(),
|
||||
raw_owner: value.gateway_owner_address.clone(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
let gateway_owner_address = value
|
||||
.gateway_owner_address
|
||||
.as_ref()
|
||||
.map(|raw_owner| {
|
||||
AccountId::from_str(&raw_owner).map_err(|source| {
|
||||
BadGateway::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: value.gateway_id_bs58.clone(),
|
||||
raw_owner: raw_owner.clone(),
|
||||
source,
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let gateway_listener = Url::parse(&value.gateway_listener).map_err(|source| {
|
||||
BadGateway::MalformedListener {
|
||||
@@ -241,7 +246,7 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
||||
derived_aes128_ctr_blake3_hmac_keys_bs58: value
|
||||
.derived_aes128_ctr_blake3_hmac_keys
|
||||
.to_base58_string(),
|
||||
gateway_owner_address: value.gateway_owner_address.to_string(),
|
||||
gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()),
|
||||
gateway_listener: value.gateway_listener.to_string(),
|
||||
wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()),
|
||||
}
|
||||
@@ -256,7 +261,7 @@ pub struct RemoteGatewayDetails {
|
||||
// the keys will be zeroized
|
||||
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||
|
||||
pub gateway_owner_address: AccountId,
|
||||
pub gateway_owner_address: Option<AccountId>,
|
||||
|
||||
pub gateway_listener: Url,
|
||||
|
||||
|
||||
@@ -388,7 +388,10 @@ where
|
||||
|
||||
let cfg = GatewayConfig::new(
|
||||
details.gateway_id,
|
||||
Some(details.gateway_owner_address.to_string()),
|
||||
details
|
||||
.gateway_owner_address
|
||||
.as_ref()
|
||||
.map(|o| o.to_string()),
|
||||
gateway_listener,
|
||||
);
|
||||
GatewayClient::new(
|
||||
|
||||
@@ -92,11 +92,11 @@ pub mod v1_1_33 {
|
||||
message: format!("the stored gateway id was malformed: {err}"),
|
||||
})?,
|
||||
derived_aes128_ctr_blake3_hmac_keys: Arc::new(gateway_shared_key),
|
||||
gateway_owner_address: gateway_owner.parse().map_err(|err| {
|
||||
gateway_owner_address: Some(gateway_owner.parse().map_err(|err| {
|
||||
ClientCoreError::UpgradeFailure {
|
||||
message: format!("the stored gateway owner address was malformed: {err}"),
|
||||
}
|
||||
})?,
|
||||
})?),
|
||||
gateway_listener: gateway_listener.parse().map_err(|err| {
|
||||
ClientCoreError::UpgradeFailure {
|
||||
message: format!("the stored gateway listener address was malformed: {err}"),
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::{error, warn};
|
||||
use log::{debug, error, warn};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::{nym_topology_from_detailed, NymTopology, NymTopologyError};
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
@@ -103,6 +103,12 @@ impl NymApiTopologyProvider {
|
||||
Ok(gateways) => gateways,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"there are {} mixnodes and {} gateways in total (before performance filtering)",
|
||||
mixnodes.len(),
|
||||
gateways.len()
|
||||
);
|
||||
|
||||
let topology = NymTopology::from_unordered(
|
||||
mixnodes.iter().filter(|m| {
|
||||
m.performance.round_to_integer() >= self.config.min_mixnode_performance
|
||||
|
||||
@@ -29,7 +29,7 @@ pub enum SelectedGateway {
|
||||
Remote {
|
||||
gateway_id: identity::PublicKey,
|
||||
|
||||
gateway_owner_address: AccountId,
|
||||
gateway_owner_address: Option<AccountId>,
|
||||
|
||||
gateway_listener: Url,
|
||||
|
||||
@@ -84,13 +84,19 @@ impl SelectedGateway {
|
||||
|
||||
let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?;
|
||||
|
||||
let gateway_owner_address = AccountId::from_str(&node.owner).map_err(|source| {
|
||||
ClientCoreError::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
raw_owner: node.owner,
|
||||
err: source.to_string(),
|
||||
}
|
||||
})?;
|
||||
let gateway_owner_address = node
|
||||
.owner
|
||||
.as_ref()
|
||||
.map(|raw_owner| {
|
||||
AccountId::from_str(&raw_owner).map_err(|source| {
|
||||
ClientCoreError::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
raw_owner: raw_owner.clone(),
|
||||
err: source.to_string(),
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let gateway_listener =
|
||||
Url::parse(&gateway_listener).map_err(|source| ClientCoreError::MalformedListener {
|
||||
|
||||
@@ -41,7 +41,7 @@ impl<'a> From<&'a mix::Node> for TestableNode {
|
||||
fn from(value: &'a mix::Node) -> Self {
|
||||
TestableNode {
|
||||
encoded_identity: value.identity_key.to_base58_string(),
|
||||
owner: value.owner.clone(),
|
||||
owner: value.owner.as_ref().cloned().unwrap_or_default(),
|
||||
typ: NodeType::Mixnode {
|
||||
mix_id: value.mix_id,
|
||||
},
|
||||
@@ -53,7 +53,7 @@ impl<'a> From<&'a gateway::Node> for TestableNode {
|
||||
fn from(value: &'a gateway::Node) -> Self {
|
||||
TestableNode {
|
||||
encoded_identity: value.identity_key.to_base58_string(),
|
||||
owner: value.owner.clone(),
|
||||
owner: value.owner.as_ref().cloned().unwrap_or_default(),
|
||||
typ: NodeType::Gateway,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ use nym_sphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress};
|
||||
use nym_sphinx_types::Node as SphinxNode;
|
||||
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
use std::io;
|
||||
@@ -48,7 +50,6 @@ pub enum GatewayConversionError {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Node {
|
||||
pub owner: String,
|
||||
pub host: NetworkAddress,
|
||||
// we're keeping this as separate resolved field since we do not want to be resolving the potential
|
||||
// hostname every time we want to construct a path via this node
|
||||
@@ -62,6 +63,9 @@ pub struct Node {
|
||||
|
||||
pub identity_key: identity::PublicKey,
|
||||
pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519
|
||||
|
||||
// to be removed:
|
||||
pub owner: Option<String>,
|
||||
pub version: NodeVersion,
|
||||
}
|
||||
|
||||
@@ -122,7 +126,7 @@ impl fmt::Display for Node {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Node(id: {}, owner: {}, host: {})",
|
||||
"Node(id: {}, owner: {:?}, host: {})",
|
||||
self.identity_key, self.owner, self.host,
|
||||
)
|
||||
}
|
||||
@@ -156,7 +160,7 @@ impl<'a> TryFrom<&'a GatewayBond> for Node {
|
||||
let mix_host = Self::extract_mix_host(&host, bond.gateway.mix_port)?;
|
||||
|
||||
Ok(Node {
|
||||
owner: bond.owner.as_str().to_owned(),
|
||||
owner: Some(bond.owner.as_str().to_owned()),
|
||||
host,
|
||||
mix_host,
|
||||
clients_ws_port: bond.gateway.clients_port,
|
||||
@@ -201,7 +205,7 @@ impl<'a> TryFrom<&'a DescribedGateway> for Node {
|
||||
let mix_host = SocketAddr::new(ips[0], value.bond.gateway.mix_port);
|
||||
|
||||
Ok(Node {
|
||||
owner: value.bond.owner.as_str().to_owned(),
|
||||
owner: Some(value.bond.owner.as_str().to_owned()),
|
||||
host,
|
||||
mix_host,
|
||||
clients_ws_port: self_described.mixnet_websockets.ws_port,
|
||||
@@ -225,17 +229,36 @@ impl<'a> TryFrom<&'a SkimmedNode> for Node {
|
||||
type Error = GatewayConversionError;
|
||||
|
||||
fn try_from(value: &'a SkimmedNode) -> Result<Self, Self::Error> {
|
||||
todo!()
|
||||
// Ok(Node {
|
||||
// owner: "".to_string(),
|
||||
// host: (),
|
||||
// mix_host: (),
|
||||
// clients_ws_port: 0,
|
||||
// clients_wss_port: None,
|
||||
// identity_key: (),
|
||||
// sphinx_key: (),
|
||||
// version: Default::default(),
|
||||
// })
|
||||
let Some(entry_details) = &value.entry else {
|
||||
return Err(GatewayConversionError::NotGateway);
|
||||
};
|
||||
|
||||
if value.ip_addresses.is_empty() {
|
||||
return Err(GatewayConversionError::NoIpAddressesProvided {
|
||||
gateway: value.ed25519_identity_pubkey.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
// safety: we just checked the slice is not empty
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let ip = value.ip_addresses.choose(&mut thread_rng()).unwrap();
|
||||
|
||||
let host = if let Some(hostname) = &entry_details.hostname {
|
||||
NetworkAddress::Hostname(hostname.to_string())
|
||||
} else {
|
||||
NetworkAddress::IpAddr(*ip)
|
||||
};
|
||||
|
||||
Ok(Node {
|
||||
host,
|
||||
mix_host: SocketAddr::new(*ip, value.mix_port),
|
||||
clients_ws_port: entry_details.ws_port,
|
||||
clients_wss_port: entry_details.wss_port,
|
||||
identity_key: value.ed25519_identity_pubkey.parse()?,
|
||||
sphinx_key: value.x25519_sphinx_pubkey.parse()?,
|
||||
owner: None,
|
||||
version: NodeVersion::Unknown,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
-14
@@ -8,7 +8,9 @@ use nym_mixnet_contract_common::{MixId, MixNodeBond};
|
||||
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx_types::Node as SphinxNode;
|
||||
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use nym_api_requests::nym_nodes::{NodeRole, SkimmedNode};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::fmt::Formatter;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
@@ -29,6 +31,12 @@ pub enum MixnodeConversionError {
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("invalid mix layer")]
|
||||
InvalidLayer,
|
||||
|
||||
#[error("'{mixnode}' has not provided any valid ip addresses")]
|
||||
NoIpAddressesProvided { mixnode: String },
|
||||
|
||||
#[error("provided node is not a mixnode in this epoch!")]
|
||||
NotMixnode,
|
||||
}
|
||||
@@ -36,7 +44,6 @@ pub enum MixnodeConversionError {
|
||||
#[derive(Clone)]
|
||||
pub struct Node {
|
||||
pub mix_id: MixId,
|
||||
pub owner: String,
|
||||
pub host: NetworkAddress,
|
||||
// we're keeping this as separate resolved field since we do not want to be resolving the potential
|
||||
// hostname every time we want to construct a path via this node
|
||||
@@ -44,7 +51,10 @@ pub struct Node {
|
||||
pub identity_key: identity::PublicKey,
|
||||
pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519
|
||||
pub layer: Layer,
|
||||
|
||||
// to be removed:
|
||||
pub version: NodeVersion,
|
||||
pub owner: Option<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Node {
|
||||
@@ -111,7 +121,7 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node {
|
||||
|
||||
Ok(Node {
|
||||
mix_id: bond.mix_id,
|
||||
owner: bond.owner.as_str().to_owned(),
|
||||
owner: Some(bond.owner.as_str().to_owned()),
|
||||
host,
|
||||
mix_host,
|
||||
identity_key: identity::PublicKey::from_base58_string(&bond.mix_node.identity_key)?,
|
||||
@@ -126,17 +136,35 @@ impl<'a> TryFrom<&'a SkimmedNode> for Node {
|
||||
type Error = MixnodeConversionError;
|
||||
|
||||
fn try_from(value: &'a SkimmedNode) -> Result<Self, Self::Error> {
|
||||
todo!()
|
||||
// Ok(Node {
|
||||
// owner: "".to_string(),
|
||||
// host: (),
|
||||
// mix_host: (),
|
||||
// clients_ws_port: 0,
|
||||
// clients_wss_port: None,
|
||||
// identity_key: (),
|
||||
// sphinx_key: (),
|
||||
// version: Default::default(),
|
||||
// })
|
||||
if value.ip_addresses.is_empty() {
|
||||
return Err(MixnodeConversionError::NoIpAddressesProvided {
|
||||
mixnode: value.ed25519_identity_pubkey.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let layer = match value.role {
|
||||
NodeRole::Mixnode { layer } => layer
|
||||
.try_into()
|
||||
.map_err(|_| MixnodeConversionError::InvalidLayer)?,
|
||||
_ => return Err(MixnodeConversionError::NotMixnode),
|
||||
};
|
||||
|
||||
// safety: we just checked the slice is not empty
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let ip = value.ip_addresses.choose(&mut thread_rng()).unwrap();
|
||||
|
||||
let host = NetworkAddress::IpAddr(*ip);
|
||||
|
||||
Ok(Node {
|
||||
mix_id: value.node_id,
|
||||
host,
|
||||
mix_host: SocketAddr::new(*ip, value.mix_port),
|
||||
identity_key: value.ed25519_identity_pubkey.parse()?,
|
||||
sphinx_key: value.x25519_sphinx_pubkey.parse()?,
|
||||
layer,
|
||||
owner: None,
|
||||
version: NodeVersion::Unknown,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,8 @@ pub struct SerializableMixNode {
|
||||
#[serde(alias = "mix_id")]
|
||||
pub mix_id: u32,
|
||||
|
||||
pub owner: String,
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
pub owner: Option<String>,
|
||||
|
||||
pub host: String,
|
||||
|
||||
@@ -180,7 +181,8 @@ impl<'a> From<&'a mix::Node> for SerializableMixNode {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SerializableGateway {
|
||||
pub owner: String,
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
pub owner: Option<String>,
|
||||
|
||||
pub host: String,
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::models::{
|
||||
GatewayBondAnnotated, MixNodeBondAnnotated, NymNodeDescription, OffsetDateTimeJsonSchemaWrapper,
|
||||
};
|
||||
use nym_mixnet_contract_common::reward_params::Performance;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
|
||||
@@ -54,11 +55,15 @@ pub struct BasicEntryInformation {
|
||||
pub wss_port: Option<u16>,
|
||||
}
|
||||
|
||||
type NodeId = MixId;
|
||||
|
||||
// the bare minimum information needed to construct sphinx packets
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct SkimmedNode {
|
||||
// in directory v3 all nodes (mixnodes AND gateways) will have a unique id
|
||||
// pub node_id: NodeId,
|
||||
// but to keep structure consistent, introduce this field now
|
||||
pub node_id: NodeId,
|
||||
|
||||
pub ed25519_identity_pubkey: String,
|
||||
pub ip_addresses: Vec<IpAddr>,
|
||||
|
||||
@@ -103,6 +108,7 @@ impl SkimmedNode {
|
||||
impl<'a> From<&'a MixNodeBondAnnotated> for SkimmedNode {
|
||||
fn from(value: &'a MixNodeBondAnnotated) -> Self {
|
||||
SkimmedNode {
|
||||
node_id: value.mix_id(),
|
||||
ed25519_identity_pubkey: value.identity_key().to_string(),
|
||||
ip_addresses: value.ip_addresses.clone(),
|
||||
mix_port: value.mix_node().mix_port,
|
||||
@@ -119,6 +125,7 @@ impl<'a> From<&'a MixNodeBondAnnotated> for SkimmedNode {
|
||||
impl<'a> From<&'a GatewayBondAnnotated> for SkimmedNode {
|
||||
fn from(value: &'a GatewayBondAnnotated) -> Self {
|
||||
SkimmedNode {
|
||||
node_id: MixId::MAX,
|
||||
ip_addresses: value.ip_addresses.clone(),
|
||||
ed25519_identity_pubkey: value.gateway_bond.identity().clone(),
|
||||
mix_port: value.gateway_bond.gateway.mix_port,
|
||||
|
||||
Reference in New Issue
Block a user