Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bc59f94c1b | |||
| 8c28a12569 | |||
| f7387c3229 | |||
| a3460d7f67 | |||
| d7b5f4f6d6 |
@@ -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' }}
|
||||
|
||||
@@ -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
@@ -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,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,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)
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.34"
|
||||
version = "1.1.33"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
|
||||
+1
-1
@@ -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
@@ -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>",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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>",
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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,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,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,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-cli"
|
||||
version = "1.1.35"
|
||||
version = "1.1.34"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user