Compare commits

..

5 Commits

Author SHA1 Message Date
Jon Häggblad bc59f94c1b Pass errors up the call stack 2024-05-06 11:56:30 +02:00
Jon Häggblad 8c28a12569 Start adding error return types 2024-05-06 10:24:50 +02:00
Jon Häggblad f7387c3229 wip: explore timeout on ws send 2024-05-05 22:42:56 +02:00
Jon Häggblad a3460d7f67 wip 2024-05-05 21:05:01 +02:00
Jon Häggblad d7b5f4f6d6 Exlicitly drop packet router when shutdown detected
In the vpn client I've observed that 2 out of 3 times the disconnect
procedure stalls out.

Investigating in the logs these 5 are still running when we hit shutdown
timeout.

[TaskClient-nym_vpn_lib-mixnet_client_main-real_traffic_controller-ack_control-retransmission_request_listener] Polling shutdown failed: channel closed
[TaskClient-nym_vpn_lib-mixnet_client_main-real_traffic_controller-out_queue_control] Polling shutdown failed: channel closed
[TaskClient-gateway-packet-router] Polling shutdown failed: channel closed
[TaskClient-nym_vpn_lib-mixnet_client_main-gateway_transceiver] Polling shutdown failed: channel closed
[TaskClient-nym_vpn_lib-mixnet_client_main-mix_traffic_controller] Polling shutdown failed: channel closed

I _think_ what was causing the problem here is that the task client in
the packet router is not being awaited in an event loop like other
client instances.

Explictly drop it in the socket state to make sure it's not blocking
shutdown.
2024-05-05 21:05:01 +02:00
27 changed files with 171 additions and 159 deletions
@@ -30,7 +30,6 @@ jobs:
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
nymvisor_hash: ${{ steps.binary-hashes.outputs.nymvisor_hash }}
nymnode_hash: ${{ steps.binary-hashes.outputs.nymnode_hash }}
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
@@ -39,7 +38,6 @@ jobs:
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
nymvisor_version: ${{ steps.binary-versions.outputs.nymvisor_version }}
nymnode_version: ${{ steps.binary-versions.outputs.nymnode_version }}
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
@@ -83,7 +81,6 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
retention-days: 30
- id: create-release
@@ -102,7 +99,6 @@ jobs:
target/release/nym-network-statistics
target/release/nym-cli
target/release/nymvisor
target/release/nym-node
push-release-data-client:
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
-14
View File
@@ -4,20 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.3-eclipse] (2024-04-22)
- Initial release of the first iteration of the Nym Node
- Improvements to gateway functionality
- IPR development
- Removal of allow list in favour of implementing an exit policy
- Explorer delegation: enables direct delegation to nodes via the Nym Explorer
## [2024.2-fast-and-furious] (2024-03-25)
- Internal testing pre-release
## [2024.1-marabou] (2024-02-15)
**New Features:**
Generated
+16 -17
View File
@@ -2547,7 +2547,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "explorer-api"
version = "1.1.34"
version = "1.1.33"
dependencies = [
"chrono",
"clap 4.4.7",
@@ -3507,7 +3507,7 @@ dependencies = [
"futures-util",
"http 0.2.9",
"hyper 0.14.27",
"rustls 0.21.11",
"rustls 0.21.10",
"tokio",
"tokio-rustls 0.24.1",
]
@@ -5024,7 +5024,7 @@ dependencies = [
[[package]]
name = "nym-api"
version = "1.1.37"
version = "1.1.35"
dependencies = [
"anyhow",
"async-trait",
@@ -5113,7 +5113,6 @@ dependencies = [
"schemars",
"serde",
"tendermint",
"time",
"ts-rs",
]
@@ -5186,7 +5185,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.35"
version = "1.1.34"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -5267,7 +5266,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.34"
version = "1.1.33"
dependencies = [
"bs58 0.5.0",
"clap 4.4.7",
@@ -5684,7 +5683,7 @@ dependencies = [
[[package]]
name = "nym-gateway"
version = "1.1.35"
version = "1.1.33"
dependencies = [
"anyhow",
"async-trait",
@@ -5979,7 +5978,7 @@ dependencies = [
[[package]]
name = "nym-mixnode"
version = "1.1.37"
version = "1.1.35"
dependencies = [
"anyhow",
"axum",
@@ -6098,7 +6097,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.34"
version = "1.1.33"
dependencies = [
"addr",
"anyhow",
@@ -6150,7 +6149,7 @@ dependencies = [
[[package]]
name = "nym-network-statistics"
version = "1.1.34"
version = "1.1.33"
dependencies = [
"dirs 4.0.0",
"log",
@@ -6438,7 +6437,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.34"
version = "1.1.33"
dependencies = [
"bs58 0.5.0",
"clap 4.4.7",
@@ -8318,7 +8317,7 @@ dependencies = [
"once_cell",
"percent-encoding",
"pin-project-lite 0.2.13",
"rustls 0.21.11",
"rustls 0.21.10",
"rustls-native-certs",
"rustls-pemfile",
"serde",
@@ -8702,9 +8701,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.21.11"
version = "0.21.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4"
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
dependencies = [
"log",
"ring 0.17.4",
@@ -10101,7 +10100,7 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls 0.21.11",
"rustls 0.21.10",
"tokio",
]
@@ -10162,7 +10161,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
"rustls 0.21.11",
"rustls 0.21.10",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.24.1",
@@ -10596,7 +10595,7 @@ dependencies = [
"httparse",
"log",
"rand 0.8.5",
"rustls 0.21.11",
"rustls 0.21.10",
"sha1",
"thiserror",
"url",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.34"
version = "1.1.33"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.34"
version = "1.1.33"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
use crate::error::ClientCoreError;
use crate::spawn_future;
use log::*;
use nym_sphinx::forwarding::packet::MixPacket;
@@ -60,8 +61,15 @@ impl MixTrafficController {
)
}
async fn on_messages(&mut self, mut mix_packets: Vec<MixPacket>) {
async fn on_messages(
&mut self,
mut mix_packets: Vec<MixPacket>,
) -> Result<(), ClientCoreError> {
debug_assert!(!mix_packets.is_empty());
info!(
"JON: MixTrafficController: Sending {} sphinx packets to the gateway",
mix_packets.len()
);
let result = if mix_packets.len() == 1 {
let mix_packet = mix_packets.pop().unwrap();
@@ -72,42 +80,56 @@ impl MixTrafficController {
.await
};
match result {
let r = match result {
Err(err) => {
error!("Failed to send sphinx packet(s) to the gateway: {err}");
self.consecutive_gateway_failure_count += 1;
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
// todo: in the future this should initiate a 'graceful' shutdown or try
// to reconnect?
panic!("failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead. Can't do anything about it yet :(")
Err(ClientCoreError::GatewayMaxRetriesExceeded)
} else {
Err(ClientCoreError::GatewayClientSendError {
gateway_client_error: err.to_string(),
})
}
}
Ok(_) => {
trace!("We *might* have managed to forward sphinx packet(s) to the gateway!");
self.consecutive_gateway_failure_count = 0;
Ok(())
}
}
};
info!("JON: MixTrafficController: done sending sphinx packets to the gateway");
r
}
pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) {
spawn_future(async move {
debug!("Started MixTrafficController with graceful shutdown support");
// let mut shutdown0 = shutdown.recv_with_delay();
// tokio::pin!(shutdown0);
loop {
tokio::select! {
biased;
_ = shutdown.recv_with_delay() => {
// _ = &mut shutdown0 => {
log::trace!("MixTrafficController: Received shutdown");
break;
}
mix_packets = self.mix_rx.recv() => match mix_packets {
Some(mix_packets) => {
self.on_messages(mix_packets).await;
log::info!("JON: MixTrafficController: mix_rx recv");
if let Err(err) = self.on_messages(mix_packets).await {
log::error!("MixTrafficController: failed to send mix packets to the gateway: {err}");
}
log::info!("JON: MixTrafficController: done with mix_rx recv");
},
None => {
log::trace!("MixTrafficController: Stopping since channel closed");
break;
}
},
_ = shutdown.recv_with_delay() => {
log::trace!("MixTrafficController: Received shutdown");
break;
}
}
}
shutdown.recv_timeout().await;
@@ -19,6 +19,12 @@ use futures::channel::{mpsc, oneshot};
#[error(transparent)]
pub struct ErasedGatewayError(Box<dyn std::error::Error + Send + Sync>);
impl ErasedGatewayError {
pub fn downcast<T: std::error::Error + 'static>(&self) -> Option<&T> {
self.0.downcast_ref::<T>()
}
}
fn erase_err<E: std::error::Error + Send + Sync + 'static>(err: E) -> ErasedGatewayError {
ErasedGatewayError(Box::new(err))
}
@@ -40,6 +46,7 @@ pub trait GatewaySender {
&mut self,
packets: Vec<MixPacket>,
) -> Result<(), ErasedGatewayError> {
log::info!("GatewaySender::batch_send_mix_packets - sending {} packets", packets.len());
// allow for optimisation when sending multiple packets
for packet in packets {
self.send_mix_packet(packet).await?;
@@ -78,7 +85,10 @@ impl<G: GatewayTransceiver + ?Sized + Send> GatewayTransceiver for Box<G> {
impl<G: GatewaySender + ?Sized + Send> GatewaySender for Box<G> {
#[inline]
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
(**self).send_mix_packet(packet).await
log::info!("JON: Box<GatewaySender>::send_mix_packet - sending a packet");
let r = (**self).send_mix_packet(packet).await;
log::info!("JON: Box<GatewaySender>::send_mix_packet - sent a packet");
r
}
#[inline]
@@ -86,7 +96,10 @@ impl<G: GatewaySender + ?Sized + Send> GatewaySender for Box<G> {
&mut self,
packets: Vec<MixPacket>,
) -> Result<(), ErasedGatewayError> {
(**self).batch_send_mix_packets(packets).await
log::info!("JON: Box<GatewaySender>::batch_send_mix_packets - sending {} packets", packets.len());
let r = (**self).batch_send_mix_packets(packets).await;
log::info!("JON: Box<GatewaySender>::batch_send_mix_packets - sent packets");
r
}
}
@@ -130,20 +143,26 @@ where
St: Send,
{
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
self.gateway_client
log::info!("JON: RemoteGateway::send_mix_packet - sending a packet");
let r = self.gateway_client
.send_mix_packet(packet)
.await
.map_err(erase_err)
.map_err(erase_err);
log::info!("JON: RemoteGateway::send_mix_packet - sent a packet");
r
}
async fn batch_send_mix_packets(
&mut self,
packets: Vec<MixPacket>,
) -> Result<(), ErasedGatewayError> {
self.gateway_client
log::info!("JON: RemoteGateway::batch_send_mix_packets - sending {} packets", packets.len());
let r = self.gateway_client
.batch_send_mix_packets(packets)
.await
.map_err(erase_err)
.map_err(erase_err);
log::info!("JON: RemoteGateway::batch_send_mix_packets - sent packets");
r
}
}
@@ -203,10 +222,13 @@ mod nonwasm_sealed {
#[async_trait]
impl GatewaySender for LocalGateway {
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
self.packet_forwarder
log::info!("JON: LocalGateway::send_mix_packet - sending a packet");
let r = self.packet_forwarder
.unbounded_send(packet)
.map_err(|err| err.into_send_error())
.map_err(erase_err)
.map_err(erase_err);
log::info!("JON: LocalGateway::send_mix_packet - sent a packet");
r
}
}
@@ -261,6 +283,7 @@ impl GatewayReceiver for MockGateway {
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl GatewaySender for MockGateway {
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
log::info!("MockGateway::send_mix_packet - sending a packet");
self.sent.push(packet);
Ok(())
}
@@ -632,15 +632,23 @@ where
}
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
self.action_sender
if self
.action_sender
.unbounded_send(Action::UpdateDelay(id, new_delay))
.expect("action control task has died")
.is_err()
{
log::debug!("action control task has died");
}
}
pub(crate) fn insert_pending_acks(&self, pending_acks: Vec<PendingAcknowledgement>) {
self.action_sender
if self
.action_sender
.unbounded_send(Action::new_insert(pending_acks))
.expect("action control task has died")
.is_err()
{
log::debug!("action control task has died");
}
}
// tells real message sender (with the poisson timer) to send this to the mix network
@@ -198,7 +198,9 @@ where
// queues and client load rather than the required delay. So realistically we can treat
// whatever is about to happen as negligible additional delay.
trace!("{} is about to get sent to the mixnet", frag_id);
self.sent_notifier.unbounded_send(frag_id).unwrap();
if self.sent_notifier.unbounded_send(frag_id).is_err() {
debug!("Failed to notify about sent packet");
}
}
fn loop_cover_message_size(&mut self) -> PacketSize {
@@ -270,7 +272,8 @@ where
};
if let Err(err) = self.mix_tx.send(vec![next_message]).await {
log::error!("Failed to send: {err}");
log::debug!("Failed to send: {err}");
return;
} else {
let event = if fragment_id.is_some() {
PacketStatisticsEvent::RealPacketSent(packet_size)
+8
View File
@@ -78,6 +78,9 @@ pub enum ClientCoreError {
source: tungstenite::Error,
},
#[error("max number of retries for gateway connection has been exceeded")]
GatewayMaxRetriesExceeded,
#[cfg(target_arch = "wasm32")]
#[error("failed to establish gateway connection (wasm)")]
GatewayJsConnectionFailure,
@@ -88,6 +91,11 @@ pub enum ClientCoreError {
#[error("timed out while trying to establish gateway connection")]
GatewayConnectionTimeout,
#[error("failed to send sphinx packet to the gateway: {gateway_client_error}")]
GatewayClientSendError {
gateway_client_error: String,
},
#[error("no ping measurements for the gateway ({identity}) performed")]
NoGatewayMeasurements { identity: String },
@@ -333,6 +333,7 @@ impl<C, St> GatewayClient<C, St> {
&mut self,
msg: Message,
) -> Result<ServerResponse, GatewayClientError> {
log::info!("JON: GatewayClient: send_websocket_message");
let should_restart_mixnet_listener = if self.connection.is_partially_delegated() {
self.recover_socket_connection().await?;
true
@@ -351,6 +352,7 @@ impl<C, St> GatewayClient<C, St> {
if should_restart_mixnet_listener {
self.start_listening_for_mixnet_messages()?;
}
log::info!("JON: GatewayClient: send_websocket_message done");
response
}
@@ -358,7 +360,8 @@ impl<C, St> GatewayClient<C, St> {
&mut self,
messages: Vec<Message>,
) -> Result<(), GatewayClientError> {
match self.connection {
log::info!("JON: GatewayClient: batch_send_websocket_messages_without_response");
let r = match self.connection {
SocketState::Available(ref mut conn) => {
let stream_messages: Vec<_> = messages.into_iter().map(Ok).collect();
let mut send_stream = futures::stream::iter(stream_messages);
@@ -381,14 +384,17 @@ impl<C, St> GatewayClient<C, St> {
}
SocketState::NotConnected => Err(GatewayClientError::ConnectionNotEstablished),
_ => Err(GatewayClientError::ConnectionInInvalidState),
}
};
log::info!("JON: GatewayClient: batch_send_websocket_messages_without_response done");
r
}
async fn send_websocket_message_without_response(
&mut self,
msg: Message,
) -> Result<(), GatewayClientError> {
match self.connection {
log::info!("JON: GatewayClient: send_websocket_message_without_response");
let r = match self.connection {
SocketState::Available(ref mut conn) => Ok(conn.send(msg).await?),
SocketState::PartiallyDelegated(ref mut partially_delegated) => {
if let Err(err) = partially_delegated.send_without_response(msg).await {
@@ -404,7 +410,9 @@ impl<C, St> GatewayClient<C, St> {
}
SocketState::NotConnected => Err(GatewayClientError::ConnectionNotEstablished),
_ => Err(GatewayClientError::ConnectionInInvalidState),
}
};
log::info!("JON: GatewayClient: send_websocket_message_without_response done");
r
}
fn check_gateway_protocol(
@@ -658,6 +666,7 @@ impl<C, St> GatewayClient<C, St> {
&mut self,
packets: Vec<MixPacket>,
) -> Result<(), GatewayClientError> {
info!("JON: GatewayClient: batch_send_mix_packets");
debug!("Sending {} mix packets", packets.len());
if !self.authenticated {
@@ -684,10 +693,11 @@ impl<C, St> GatewayClient<C, St> {
})
.collect();
if let Err(err) = self
let r = if let Err(err) = self
.batch_send_websocket_messages_without_response(messages)
.await
{
log::error!("GatewayClient: Failed to send sphinx packets to the gateway: {err}");
if err.is_closed_connection() && self.should_reconnect_on_failure {
self.attempt_reconnection().await
} else {
@@ -695,14 +705,17 @@ impl<C, St> GatewayClient<C, St> {
}
} else {
Ok(())
}
};
log::info!("JON: GatewayClient: batch_send_mix_packets done");
r
}
async fn send_with_reconnection_on_failure(
&mut self,
msg: Message,
) -> Result<(), GatewayClientError> {
if let Err(err) = self.send_websocket_message_without_response(msg).await {
log::info!("JON: GatewayClient: send_with_reconnection_on_failure");
let r = if let Err(err) = self.send_websocket_message_without_response(msg).await {
if err.is_closed_connection() && self.should_reconnect_on_failure {
debug!("Going to attempt a reconnection");
self.attempt_reconnection().await
@@ -712,7 +725,9 @@ impl<C, St> GatewayClient<C, St> {
}
} else {
Ok(())
}
};
log::info!("JON: GatewayClient: send_with_reconnection_on_failure done");
r
}
pub async fn send_ping_message(&mut self) -> Result<(), GatewayClientError> {
@@ -731,6 +746,7 @@ impl<C, St> GatewayClient<C, St> {
&mut self,
mix_packet: MixPacket,
) -> Result<(), GatewayClientError> {
log::info!("JON: GatewayClient: send_mix_packet");
if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
}
@@ -750,7 +766,9 @@ impl<C, St> GatewayClient<C, St> {
.as_ref()
.expect("no shared key present even though we're authenticated!"),
);
self.send_with_reconnection_on_failure(msg).await
let r = self.send_with_reconnection_on_failure(msg).await;
log::info!("JON: GatewayClient: send_mix_packet done");
r
}
async fn recover_socket_connection(&mut self) -> Result<(), GatewayClientError> {
@@ -74,6 +74,9 @@ pub enum GatewayClientError {
#[error("Timed out")]
Timeout,
#[error("timeout sending ws message to the gateway")]
TimeoutOnSendingWs,
#[error("Failed to send mixnet message")]
MixnetMsgSenderFailedToSend,
@@ -93,6 +96,7 @@ pub enum GatewayClientError {
impl GatewayClientError {
pub fn is_closed_connection(&self) -> bool {
log::info!("GatewayClientError::is_closed_connection");
match self {
GatewayClientError::NetworkError(ws_err) => match ws_err {
WsError::AlreadyClosed | WsError::ConnectionClosed => true,
@@ -158,6 +158,9 @@ impl PartiallyDelegated {
_ = shutdown.recv() => {
log::trace!("GatewayClient listener: Received shutdown");
log::debug!("GatewayClient listener: Exiting");
// The packet router a task client, and as such we need to make
// sure it's dropped to not stall the shutdown process.
// drop(packet_router);
return;
}
_ = &mut notify_receiver => {
@@ -214,16 +217,31 @@ impl PartiallyDelegated {
&mut self,
msg: Message,
) -> Result<(), GatewayClientError> {
Ok(self.sink_half.send(msg).await?)
log::info!("JON: PartiallyDelegated::send_without_response - sending a message");
// let r = self.sink_half.send(msg).await;
// Ok(r?)
let r = tokio::time::timeout(Duration::from_secs(3), self.sink_half.send(msg)).await;
let rr = match r {
Ok(rr) => Ok(rr?),
Err(_) => {
log::error!("JON: PartiallyDelegated::send_without_response - timeout sending a message");
Err(GatewayClientError::TimeoutOnSendingWs)
}
};
log::info!("JON: PartiallyDelegated::send_without_response - sent a message: {rr:?}");
rr
}
pub(crate) async fn batch_send_without_response(
&mut self,
messages: Vec<Message>,
) -> Result<(), GatewayClientError> {
log::info!("JON: PartiallyDelegated::batch_send_without_response - sending {} messages", messages.len());
let stream_messages: Vec<_> = messages.into_iter().map(Ok).collect();
let mut send_stream = futures::stream::iter(stream_messages);
Ok(self.sink_half.send_all(&mut send_stream).await?)
let r = Ok(self.sink_half.send_all(&mut send_stream).await?);
log::info!("JON: PartiallyDelegated::batch_send_without_response - sent messages");
r
}
pub(crate) async fn merge(self) -> Result<WsConn, GatewayClientError> {
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "explorer-api"
version = "1.1.34"
version = "1.1.33"
edition = "2021"
license.workspace = true
+1 -1
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-gateway"
license = "GPL-3.0"
version = "1.1.35"
version = "1.1.33"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+1 -1
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-mixnode"
license = "GPL-3.0"
version = "1.1.37"
version = "1.1.35"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
-2
View File
@@ -1,8 +1,6 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
#![allow(unused)]
use crate::node::http::legacy::description::description;
use crate::node::http::legacy::hardware::hardware;
use crate::node::http::legacy::state::MixnodeAppState;
+1 -1
View File
@@ -105,7 +105,7 @@ impl<'a> HttpApiBuilder<'a> {
let router = nym_node_http_api::NymNodeRouter::new(config, None, None);
let server = router
// .with_merged(legacy::routes(self.legacy_mixnode, self.legacy_descriptor))
.with_merged(legacy::routes(self.legacy_mixnode, self.legacy_descriptor))
.build_server(&bind_address)?
.with_task_client(task_client);
tokio::spawn(async move { server.run().await });
+1 -1
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-api"
license = "GPL-3.0"
version = "1.1.37"
version = "1.1.35"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+1 -3
View File
@@ -15,14 +15,12 @@ schemars = { workspace = true, features = ["preserve_order"] }
serde = { workspace = true, features = ["derive"] }
ts-rs = { workspace = true, optional = true }
tendermint = { workspace = true }
time = { workspace = true, features = ["serde", "parsing", "formatting"] }
# for serde on secp256k1 signatures
ecdsa = { version = "0.16", features = ["serde"] }
nym-credentials-interface = { path = "../../common/credentials-interface" }
nym-crypto = { path = "../../common/crypto", features = ["serde", "asymmetric"] }
nym-crypto = { path = "../../common/crypto", features = ["serde", "asymmetric"]}
nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false }
-67
View File
@@ -10,15 +10,11 @@ use nym_mixnet_contract_common::{
GatewayBond, IdentityKey, Interval, MixId, MixNode, Percent, RewardedSetNodeStatus,
};
use nym_node_requests::api::v1::node::models::BinaryBuildInformationOwned;
use schemars::gen::SchemaGenerator;
use schemars::schema::{InstanceType, Schema, SchemaObject};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::net::IpAddr;
use std::ops::{Deref, DerefMut};
use std::{fmt, time::Duration};
use time::OffsetDateTime;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
pub struct RequestError {
@@ -408,71 +404,8 @@ impl From<nym_node_requests::api::v1::gateway::models::WebSockets> for WebSocket
}
}
const fn unix_epoch() -> OffsetDateTime {
OffsetDateTime::UNIX_EPOCH
}
// for all intents and purposes it's just OffsetDateTime, but we need JsonSchema...
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct OffsetDateTimeJsonSchemaWrapper(#[serde(default = "unix_epoch")] pub OffsetDateTime);
impl Default for OffsetDateTimeJsonSchemaWrapper {
fn default() -> Self {
OffsetDateTimeJsonSchemaWrapper(unix_epoch())
}
}
impl From<OffsetDateTimeJsonSchemaWrapper> for OffsetDateTime {
fn from(value: OffsetDateTimeJsonSchemaWrapper) -> Self {
value.0
}
}
impl From<OffsetDateTime> for OffsetDateTimeJsonSchemaWrapper {
fn from(value: OffsetDateTime) -> Self {
OffsetDateTimeJsonSchemaWrapper(value)
}
}
impl Deref for OffsetDateTimeJsonSchemaWrapper {
type Target = OffsetDateTime;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for OffsetDateTimeJsonSchemaWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
// implementation taken from: https://github.com/GREsau/schemars/pull/207
impl JsonSchema for OffsetDateTimeJsonSchemaWrapper {
fn is_referenceable() -> bool {
false
}
fn schema_name() -> String {
"DateTime".into()
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some("date-time".into()),
..Default::default()
}
.into()
}
}
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
pub struct NymNodeDescription {
#[serde(default)]
pub last_polled: OffsetDateTimeJsonSchemaWrapper,
pub host_information: HostInformation,
// TODO: do we really care about ALL build info or just the version?
+2 -4
View File
@@ -16,7 +16,6 @@ use nym_mixnet_contract_common::Gateway;
use nym_node_requests::api::client::{NymNodeApiClientError, NymNodeApiClientExt};
use std::collections::HashMap;
use thiserror::Error;
use time::OffsetDateTime;
// type alias for ease of use
pub type DescribedNodes = HashMap<IdentityKey, NymNodeDescription>;
@@ -183,7 +182,6 @@ async fn get_gateway_description(
let description = NymNodeDescription {
host_information: host_info.data.into(),
last_polled: OffsetDateTime::now_utc().into(),
build_information: build_info,
network_requester,
ip_packet_router,
@@ -213,7 +211,7 @@ impl CacheItemProvider for NodeDescriptionProvider {
}
// TODO: somehow bypass the 'higher-ranked lifetime error' and remove that redundant clone
let node_description = stream::iter(
let websockets = stream::iter(
gateways
// .deref()
// .clone()
@@ -234,7 +232,7 @@ impl CacheItemProvider for NodeDescriptionProvider {
.collect::<HashMap<_, _>>()
.await;
Ok(node_description)
Ok(websockets)
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym_wallet"
version = "1.2.13"
version = "1.2.12"
description = "Nym Native Wallet"
authors = ["Nym Technologies SA"]
license = ""
+1 -1
View File
@@ -1,7 +1,7 @@
{
"package": {
"productName": "nym-wallet",
"version": "1.2.13"
"version": "1.2.12"
},
"build": {
"distDir": "../dist",
@@ -4,7 +4,7 @@
[package]
name = "nym-network-requester"
license = "GPL-3.0"
version = "1.1.34"
version = "1.1.33"
authors.workspace = true
edition.workspace = true
rust-version = "1.70"
@@ -1,6 +1,6 @@
[package]
name = "nym-network-statistics"
version = "1.1.34"
version = "1.1.33"
edition = "2021"
license.workspace = true
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-cli"
version = "1.1.35"
version = "1.1.34"
authors.workspace = true
edition = "2021"
license.workspace = true