Compare commits

..

3 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu fb3ec1e02e Connection fd callback before actual connection (#5494) 2025-02-27 10:53:04 +02:00
Jędrzej Stuczyński 26f97d3c34 dont query for ecash apis unless necessary (#5508) 2025-02-24 10:59:06 +00:00
benedettadavico 63a8f96ea5 bump versions 2025-02-19 12:13:24 +01:00
49 changed files with 1531 additions and 1275 deletions
Generated
+628 -661
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -322,7 +322,7 @@ serde_with = "3.9.0"
serde_yaml = "0.9.25"
sha2 = "0.10.8"
si-scale = "0.2.3"
sphinx-packet = "0.3.1"
sphinx-packet = "0.1.1"
sqlx = "0.7.4"
strum = "0.26"
strum_macros = "0.26"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.48"
version = "1.1.49"
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.48"
version = "1.1.49"
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"
+4 -7
View File
@@ -105,26 +105,24 @@ impl<C, St: Storage> BandwidthController<C, St> {
async fn get_aggregate_verification_key(
&self,
epoch_id: EpochId,
apis: &mut ApiClientsWrapper,
ecash_apis: &mut ApiClientsWrapper<'_, C>,
) -> Result<VerificationKeyAuth, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
get_aggregate_verification_key(&self.storage, epoch_id, ecash_apis).await
}
async fn get_coin_index_signatures(
&self,
epoch_id: EpochId,
apis: &mut ApiClientsWrapper,
ecash_apis: &mut ApiClientsWrapper<'_, C>,
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
get_coin_index_signatures(&self.storage, epoch_id, ecash_apis).await
}
@@ -132,13 +130,12 @@ impl<C, St: Storage> BandwidthController<C, St> {
&self,
epoch_id: EpochId,
expiration_date: Date,
apis: &mut ApiClientsWrapper,
ecash_apis: &mut ApiClientsWrapper<'_, C>,
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
get_expiration_date_signatures(&self.storage, epoch_id, expiration_date, ecash_apis).await
}
@@ -154,7 +151,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
{
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
let expiration_date = retrieved_ticketbook.ticketbook.expiration_date();
let mut api_clients = Default::default();
let mut api_clients = ApiClientsWrapper::new(&self.client, epoch_id);
let verification_key = self
.get_aggregate_verification_key(epoch_id, &mut api_clients)
+64 -21
View File
@@ -21,30 +21,67 @@ use rand::thread_rng;
use std::fmt::Display;
use std::future::Future;
// it really doesn't need the RwLock because it's never moved across tasks,
// but we need all the Send/Sync action
#[derive(Default)]
pub(crate) struct ApiClientsWrapper(Option<Vec<EcashApiClient>>);
impl ApiClientsWrapper {
pub(crate) async fn get_or_init<C>(
pub(crate) trait EcashClientsProvider {
async fn try_get_ecash_clients(
&mut self,
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>;
}
impl EcashClientsProvider for Vec<EcashApiClient> {
async fn try_get_ecash_clients(
&mut self,
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
Ok(self.clone())
}
}
impl<C> EcashClientsProvider for &mut ApiClientsWrapper<'_, C>
where
C: DkgQueryClient + Sync + Send,
{
async fn try_get_ecash_clients(
&mut self,
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
self.clients().await
}
}
pub(crate) enum ApiClientsWrapper<'a, C> {
Uninitialised {
query_client: &'a C,
epoch_id: EpochId,
dkg_client: &C,
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
},
Cached {
clients: Vec<EcashApiClient>,
},
}
impl<'a, C> ApiClientsWrapper<'a, C> {
pub(crate) fn new(query_client: &'a C, epoch_id: EpochId) -> Self {
ApiClientsWrapper::Uninitialised {
query_client,
epoch_id,
}
}
async fn clients(&mut self) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
{
if let Some(cached) = &self.0 {
return Ok(cached.clone());
match self {
ApiClientsWrapper::Uninitialised {
query_client,
epoch_id,
} => {
let clients = all_ecash_api_clients(*query_client, *epoch_id).await?;
*self = ApiClientsWrapper::Cached {
clients: clients.clone(),
};
Ok(clients)
}
ApiClientsWrapper::Cached { clients } => Ok(clients.clone()),
}
let clients = all_ecash_api_clients(dkg_client, epoch_id).await?;
// technically we don't have to be cloning all the clients here, but it's way simpler than
// dealing with locking and whatnot given the performance penalty is negligible
self.0 = Some(clients.clone());
Ok(clients)
}
}
@@ -76,7 +113,7 @@ where
pub(crate) async fn get_aggregate_verification_key<St>(
storage: &St,
epoch_id: EpochId,
ecash_apis: Vec<EcashApiClient>,
mut ecash_apis: impl EcashClientsProvider,
) -> Result<VerificationKeyAuth, BandwidthControllerError>
where
St: Storage,
@@ -90,6 +127,8 @@ where
return Ok(stored);
};
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
let master_vk = query_random_apis_until_success(
ecash_apis,
|api| async move { api.api_client.master_verification_key(Some(epoch_id)).await },
@@ -115,7 +154,7 @@ where
pub(crate) async fn get_coin_index_signatures<St>(
storage: &St,
epoch_id: EpochId,
ecash_apis: Vec<EcashApiClient>,
mut ecash_apis: impl EcashClientsProvider,
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
where
St: Storage,
@@ -129,6 +168,8 @@ where
return Ok(stored);
};
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
let index_sigs = query_random_apis_until_success(
ecash_apis,
|api| async move {
@@ -159,7 +200,7 @@ pub(crate) async fn get_expiration_date_signatures<St>(
storage: &St,
epoch_id: EpochId,
expiration_date: Date,
ecash_apis: Vec<EcashApiClient>,
mut ecash_apis: impl EcashClientsProvider,
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
where
St: Storage,
@@ -173,6 +214,8 @@ where
return Ok(stored);
};
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
let expiration_sigs = query_random_apis_until_success(
ecash_apis,
|api| async move {
@@ -204,15 +204,15 @@ impl<C, St> GatewayClient<C, St> {
"Attemting to establish connection to gateway at: {}",
self.gateway_address
);
let (ws_stream, _) = connect_async(&self.gateway_address).await?;
let (ws_stream, _) = connect_async(
&self.gateway_address,
#[cfg(unix)]
self.connection_fd_callback.clone(),
)
.await?;
self.connection = SocketState::Available(Box::new(ws_stream));
#[cfg(unix)]
if let (Some(callback), Some(fd)) = (self.connection_fd_callback.as_ref(), self.ws_fd()) {
callback.as_ref()(fd);
}
Ok(())
}
@@ -1,6 +1,11 @@
use crate::error::GatewayClientError;
use nym_http_api_client::HickoryDnsResolver;
#[cfg(unix)]
use std::{
os::fd::{AsRawFd, RawFd},
sync::Arc,
};
use tokio::net::TcpStream;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use tungstenite::handshake::client::Response;
@@ -11,7 +16,10 @@ use std::net::SocketAddr;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) async fn connect_async(
endpoint: &str,
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), GatewayClientError> {
use tokio::net::TcpSocket;
let resolver = HickoryDnsResolver::default();
let uri =
Url::parse(endpoint).map_err(|_| GatewayClientError::InvalidUrl(endpoint.to_owned()))?;
@@ -37,14 +45,41 @@ pub(crate) async fn connect_async(
}
};
let stream = TcpStream::connect(&sock_addrs[..]).await.map_err(|error| {
GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
source: error.into(),
let mut stream = Err(GatewayClientError::NoEndpointForConnection {
address: endpoint.to_owned(),
});
for sock_addr in sock_addrs {
let socket = if sock_addr.is_ipv4() {
TcpSocket::new_v4()
} else {
TcpSocket::new_v6()
}
})?;
.map_err(|err| GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
source: err.into(),
})?;
tokio_tungstenite::client_async_tls(endpoint, stream)
#[cfg(unix)]
if let Some(callback) = connection_fd_callback.as_ref() {
callback.as_ref()(socket.as_raw_fd());
}
match socket.connect(sock_addr).await {
Ok(s) => {
stream = Ok(s);
break;
}
Err(err) => {
stream = Err(GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
source: err.into(),
});
continue;
}
}
}
tokio_tungstenite::client_async_tls(endpoint, stream?)
.await
.map_err(|error| GatewayClientError::NetworkConnectionFailed {
address: endpoint.to_owned(),
@@ -43,6 +43,9 @@ pub enum GatewayClientError {
#[error("connection failed: {address}: {source}")]
NetworkConnectionFailed { address: String, source: WsError },
#[error("no socket address for endpoint: {address}")]
NoEndpointForConnection { address: String },
#[error("Invalid URL: {0}")]
InvalidUrl(String),
+3 -2
View File
@@ -37,10 +37,11 @@ nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
rand_chacha = { workspace = true }
[features]
default = []
default = ["sphinx"]
aead = ["dep:aead", "aead/std", "aes-gcm-siv", "generic-array"]
serde = ["dep:serde", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"]
asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"]
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array", "sha2"]
stream_cipher = ["aes", "ctr", "cipher", "generic-array"]
sphinx = ["nym-sphinx-types/sphinx"]
sphinx = ["nym-sphinx-types/sphinx"]
outfox = ["nym-sphinx-types/outfox"]
+100 -18
View File
@@ -202,18 +202,6 @@ impl PemStorableKey for PublicKey {
}
}
impl From<x25519_dalek::PublicKey> for PublicKey {
fn from(public_key: x25519_dalek::PublicKey) -> Self {
PublicKey(public_key)
}
}
impl From<PublicKey> for x25519_dalek::PublicKey {
fn from(public_key: PublicKey) -> Self {
public_key.0
}
}
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct PrivateKey(x25519_dalek::StaticSecret);
@@ -320,15 +308,109 @@ impl PemStorableKey for PrivateKey {
}
}
impl From<x25519_dalek::StaticSecret> for PrivateKey {
fn from(secret: x25519_dalek::StaticSecret) -> Self {
PrivateKey(secret)
// compatibility with sphinx keys:
#[cfg(feature = "sphinx")]
impl From<PublicKey> for nym_sphinx_types::PublicKey {
fn from(key: PublicKey) -> Self {
nym_sphinx_types::PublicKey::from(key.to_bytes())
}
}
impl AsRef<x25519_dalek::StaticSecret> for PrivateKey {
fn as_ref(&self) -> &x25519_dalek::StaticSecret {
&self.0
#[cfg(feature = "sphinx")]
impl<'a> From<&'a PublicKey> for nym_sphinx_types::PublicKey {
fn from(key: &'a PublicKey) -> Self {
nym_sphinx_types::PublicKey::from((*key).to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl From<nym_sphinx_types::PublicKey> for PublicKey {
fn from(pub_key: nym_sphinx_types::PublicKey) -> Self {
Self(x25519_dalek::PublicKey::from(*pub_key.as_bytes()))
}
}
#[cfg(feature = "sphinx")]
impl From<PrivateKey> for nym_sphinx_types::PrivateKey {
fn from(key: PrivateKey) -> Self {
nym_sphinx_types::PrivateKey::from(key.to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl<'a> From<&'a PrivateKey> for nym_sphinx_types::PrivateKey {
fn from(key: &'a PrivateKey) -> Self {
nym_sphinx_types::PrivateKey::from(key.to_bytes())
}
}
#[cfg(feature = "sphinx")]
impl From<nym_sphinx_types::PrivateKey> for PrivateKey {
fn from(private_key: nym_sphinx_types::PrivateKey) -> Self {
let private_key_bytes = private_key.to_bytes();
assert_eq!(private_key_bytes.len(), PRIVATE_KEY_SIZE);
Self::from_bytes(&private_key_bytes).unwrap()
}
}
#[cfg(test)]
mod sphinx_key_conversion {
use super::*;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
pub(super) fn test_rng() -> ChaCha20Rng {
let dummy_seed = [42u8; 32];
ChaCha20Rng::from_seed(dummy_seed)
}
const NUM_ITERATIONS: usize = 100;
#[test]
fn works_for_forward_conversion() {
let mut rng = test_rng();
for _ in 0..NUM_ITERATIONS {
let keys = KeyPair::new(&mut rng);
let private = &keys.private_key;
let public = &keys.public_key;
let dummy_remote = KeyPair::new(&mut rng);
let dh1 = private.diffie_hellman(&dummy_remote.public_key);
let public_bytes = public.to_bytes();
let sphinx_private: nym_sphinx_types::PrivateKey = private.into();
let recovered_private = PrivateKey::from(sphinx_private);
let dh2 = recovered_private.diffie_hellman(&dummy_remote.public_key);
let sphinx_public: nym_sphinx_types::PublicKey = public.into();
let recovered_public = PublicKey::from(sphinx_public);
assert_eq!(public_bytes, recovered_public.to_bytes());
// even though the byte representation of the private key changed, the resultant DH is the same
// which is what matters
assert_eq!(dh1, dh2);
}
}
#[test]
fn works_for_backward_conversion() {
for _ in 0..NUM_ITERATIONS {
let (sphinx_private, sphinx_public) = nym_sphinx_types::crypto::keygen();
let private_bytes = sphinx_private.to_bytes();
let public_bytes = sphinx_public.as_bytes();
let private: PrivateKey = sphinx_private.into();
let recovered_sphinx_private: nym_sphinx_types::PrivateKey = private.into();
let public: PublicKey = sphinx_public.into();
let recovered_sphinx_public: nym_sphinx_types::PublicKey = public.into();
assert_eq!(private_bytes, recovered_sphinx_private.to_bytes());
assert_eq!(public_bytes, recovered_sphinx_public.as_bytes());
}
}
}
+2
View File
@@ -48,10 +48,12 @@ features = ["sync"]
[features]
default = ["sphinx"]
sphinx = [
"nym-crypto/sphinx",
"nym-sphinx-params/sphinx",
"nym-sphinx-types/sphinx",
]
outfox = [
"nym-crypto/outfox",
"nym-sphinx-params/outfox",
"nym-sphinx-types/outfox",
]
+1 -1
View File
@@ -8,7 +8,7 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
nym-crypto = { path = "../../crypto", features = ["asymmetric", "sphinx"] } # all addresses are expressed in terms on their crypto keys
nym-crypto = { path = "../../crypto", features = ["asymmetric"] } # all addresses are expressed in terms on their crypto keys
nym-sphinx-types = { path = "../types", features = ["sphinx"] } # we need to be able to refer to some types defined inside sphinx crate
serde = { workspace = true } # implementing serialization/deserialization for some types, like `Recipient`
thiserror = { workspace = true }
@@ -12,7 +12,6 @@ rand = { workspace = true }
bs58 = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
sphinx-packet = { workspace = true }
nym-crypto = { path = "../../crypto", features = ["stream_cipher", "rand"] }
nym-sphinx-addressing = { path = "../addressing" }
@@ -7,12 +7,11 @@ use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm};
use nym_sphinx_types::{Destination, NymPacket, SURBMaterial, SphinxError, SURB};
use nym_sphinx_types::{NymPacket, SURBMaterial, SphinxError, SURB};
use nym_topology::{NymRouteProvider, NymTopologyError};
use rand::{CryptoRng, RngCore};
use serde::de::{Error as SerdeError, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use sphinx_packet::route::Node;
use std::fmt::{self, Formatter};
use std::time;
@@ -84,25 +83,6 @@ impl ReplySurb {
packet_size.plaintext_size() - ack_overhead - ReplySurbKeyDigestAlgorithm::output_size() - 1
}
pub fn construct_with_route<R>(
rng: &mut R,
destination: Destination,
average_delay: time::Duration,
route: &[Node],
) -> Result<Self, NymTopologyError>
where
R: RngCore + CryptoRng,
{
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let surb_material = SURBMaterial::new(route.to_vec(), delays, destination);
// this can't fail as we know we have a valid route to gateway and have correct number of delays
Ok(ReplySurb {
surb: surb_material.construct_SURB().unwrap(),
encryption_key: SurbEncryptionKey::new(rng),
})
}
// TODO: should this return `ReplySURBError` for consistency sake
// or keep `NymTopologyError` because it's the only error it can actually return?
pub fn construct<R>(
@@ -143,15 +123,11 @@ impl ReplySurb {
pub fn to_bytes(&self) -> Vec<u8> {
// KEY || SURB_BYTES
let bytes: Vec<u8> = self.encryption_key
self.encryption_key
.to_bytes()
.into_iter()
.chain(self.surb.to_bytes())
.collect();
assert_eq!(bytes.len(), ReplySurb::serialized_len());
bytes
.collect()
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ReplySurbError> {
@@ -170,7 +170,6 @@ impl RepliableMessage {
}
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, InvalidReplyRequestError> {
// println!("Trying to deserialize message: {} bytes", bytes.len());
if bytes.len() < SENDER_TAG_SIZE + 1 {
return Err(InvalidReplyRequestError::RequestTooShortToDeserialize);
}
@@ -560,7 +559,7 @@ mod tests {
let mut address_bytes = [0; NODE_ADDRESS_LENGTH];
rng.fill_bytes(&mut address_bytes);
let dummy_private = PrivateKey::random_from_rng(rng);
let dummy_private = PrivateKey::new_with_rng(rng);
let pub_key = (&dummy_private).into();
Node {
address: NodeAddressBytes::from_bytes(address_bytes),
-4
View File
@@ -9,7 +9,6 @@ repository = { workspace = true }
[dependencies]
bytes = { workspace = true }
cfg-if = { workspace = true }
tokio-util = { workspace = true, features = ["codec"] }
thiserror = { workspace = true }
log = { workspace = true }
@@ -21,8 +20,5 @@ nym-metrics = { path = "../../nym-metrics" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-acknowledgements = { path = "../acknowledgements" }
[features]
no-acks = []
[dev-dependencies]
tokio = { workspace = true, features = ["full"] }
+9 -14
View File
@@ -130,33 +130,28 @@ impl Decoder for NymCodec {
mod packet_encoding {
use super::*;
use nym_sphinx_types::{
Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
PrivateKey, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
crypto, Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
};
fn random_pubkey() -> nym_sphinx_types::PublicKey {
let private_key = PrivateKey::random();
(&private_key).into()
}
fn make_valid_outfox_packet(size: PacketSize) -> NymPacket {
let node1_pk = random_pubkey();
let (_, node1_pk) = crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
node1_pk,
);
let node2_pk = random_pubkey();
let (_, node2_pk) = crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([4u8; NODE_ADDRESS_LENGTH]),
node2_pk,
);
let node3_pk = random_pubkey();
let (_, node3_pk) = crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pk,
);
let node4_pk = random_pubkey();
let (_, node4_pk) = crypto::keygen();
let node4 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node4_pk,
@@ -175,17 +170,17 @@ mod packet_encoding {
}
fn make_valid_sphinx_packet(size: PacketSize) -> NymPacket {
let node1_pk = random_pubkey();
let (_, node1_pk) = crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
node1_pk,
);
let node2_pk = random_pubkey();
let (_, node2_pk) = crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([4u8; NODE_ADDRESS_LENGTH]),
node2_pk,
);
let node3_pk = random_pubkey();
let (_, node3_pk) = crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pk,
+27 -92
View File
@@ -4,10 +4,8 @@ use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressE
use nym_sphinx_params::{PacketSize, PacketType};
use nym_sphinx_types::{
Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, NymPacketError,
NymProcessedPacket, OutfoxError, PrivateKey, ProcessedPacketData, SphinxError,
Version as SphinxPacketVersion,
NymProcessedPacket, OutfoxError, PrivateKey, ProcessedPacket, SphinxError,
};
use std::fmt::Display;
use thiserror::Error;
use crate::packet::FramedNymPacket;
@@ -15,38 +13,12 @@ use nym_metrics::nanos;
use nym_sphinx_forwarding::packet::MixPacket;
#[derive(Debug)]
pub enum MixProcessingResultData {
pub enum MixProcessingResult {
/// Contains unwrapped data that should first get delayed before being sent to next hop.
ForwardHop {
packet: MixPacket,
delay: Option<SphinxDelay>,
},
ForwardHop(MixPacket, Option<SphinxDelay>),
/// Contains all data extracted out of the final hop packet that could be forwarded to the destination.
FinalHop { final_hop_data: ProcessedFinalHop },
}
#[derive(Debug, Copy, Clone)]
pub enum MixPacketVersion {
Outfox,
Sphinx(SphinxPacketVersion),
}
impl Display for MixPacketVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
MixPacketVersion::Outfox => "outfox".fmt(f),
MixPacketVersion::Sphinx(sphinx_version) => {
write!(f, "sphinx-{}", sphinx_version.value())
}
}
}
}
#[derive(Debug)]
pub struct MixProcessingResult {
pub packet_version: MixPacketVersion,
pub processing_data: MixProcessingResultData,
FinalHop(ProcessedFinalHop),
}
type ForwardAck = MixPacket;
@@ -135,63 +107,37 @@ fn perform_final_processing(
) -> Result<MixProcessingResult, PacketProcessingError> {
match packet {
NymProcessedPacket::Sphinx(packet) => {
let processing_data = match packet.data {
ProcessedPacketData::ForwardHop {
next_hop_packet,
next_hop_address,
delay,
} => process_forward_hop(
NymPacket::Sphinx(next_hop_packet),
next_hop_address,
delay,
packet_type,
),
match packet {
ProcessedPacket::ForwardHop(packet, address, delay) => {
process_forward_hop(NymPacket::Sphinx(*packet), address, delay, packet_type)
}
// right now there's no use for the surb_id included in the header - probably it should get removed from the
// sphinx all together?
ProcessedPacketData::FinalHop {
destination,
identifier: _,
payload,
} => process_final_hop(
ProcessedPacket::FinalHop(destination, _, payload) => process_final_hop(
destination,
payload.recover_plaintext()?,
packet_size,
packet_type,
),
}?;
Ok(MixProcessingResult {
packet_version: MixPacketVersion::Sphinx(packet.version),
processing_data,
})
}
}
NymProcessedPacket::Outfox(packet) => {
let next_address = *packet.next_address();
let packet = packet.into_packet();
if packet.is_final_hop() {
let processing_data = process_final_hop(
process_final_hop(
DestinationAddressBytes::from_bytes(next_address),
packet.recover_plaintext()?.to_vec(),
packet_size,
packet_type,
)?;
Ok(MixProcessingResult {
packet_version: MixPacketVersion::Outfox,
processing_data,
})
)
} else {
let packet = MixPacket::new(
let mix_packet = MixPacket::new(
NymNodeRoutingAddress::try_from_bytes(&next_address)?,
NymPacket::Outfox(packet),
PacketType::Outfox,
);
Ok(MixProcessingResult {
packet_version: MixPacketVersion::Outfox,
processing_data: MixProcessingResultData::ForwardHop {
packet,
delay: None,
},
})
Ok(MixProcessingResult::ForwardHop(mix_packet, None))
}
}
}
@@ -202,16 +148,14 @@ fn process_final_hop(
payload: Vec<u8>,
packet_size: PacketSize,
packet_type: PacketType,
) -> Result<MixProcessingResultData, PacketProcessingError> {
) -> Result<MixProcessingResult, PacketProcessingError> {
let (forward_ack, message) = split_into_ack_and_message(payload, packet_size, packet_type)?;
Ok(MixProcessingResultData::FinalHop {
final_hop_data: ProcessedFinalHop {
destination,
forward_ack,
message,
},
})
Ok(MixProcessingResult::FinalHop(ProcessedFinalHop {
destination,
forward_ack,
message,
}))
}
fn split_into_ack_and_message(
@@ -230,12 +174,8 @@ fn split_into_ack_and_message(
| PacketSize::ExtendedPacket32
| PacketSize::OutfoxRegularPacket => {
trace!("received a normal packet!");
cfg_if::cfg_if! {
if #[cfg(feature = "no-acks")] {
return Ok((None, data));
} else {
let (ack_data, message) = split_hop_data_into_ack_and_message(data, packet_type)?;
let (ack_first_hop, ack_packet) =
let (ack_data, message) = split_hop_data_into_ack_and_message(data, packet_type)?;
let (ack_first_hop, ack_packet) =
match SurbAck::try_recover_first_hop_packet(&ack_data, packet_type) {
Ok((first_hop, packet)) => (first_hop, packet),
Err(err) => {
@@ -243,10 +183,8 @@ fn split_into_ack_and_message(
return Err(err.into());
}
};
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_type);
Ok((Some(forward_ack), message))
}
}
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_type);
Ok((Some(forward_ack), message))
}
}
}
@@ -273,14 +211,11 @@ fn process_forward_hop(
forward_address: NodeAddressBytes,
delay: SphinxDelay,
packet_type: PacketType,
) -> Result<MixProcessingResultData, PacketProcessingError> {
) -> Result<MixProcessingResult, PacketProcessingError> {
let next_hop_address = NymNodeRoutingAddress::try_from(forward_address)?;
let packet = MixPacket::new(next_hop_address, packet, packet_type);
Ok(MixProcessingResultData::ForwardHop {
packet,
delay: Some(delay),
})
let mix_packet = MixPacket::new(next_hop_address, packet, packet_type);
Ok(MixProcessingResult::ForwardHop(mix_packet, Some(delay)))
}
// TODO: what more could we realistically test here?
+2 -2
View File
@@ -16,5 +16,5 @@ nym-sphinx-types = { path = "../types" }
[features]
default = ["sphinx"]
sphinx = ["nym-sphinx-types/outfox"]
outfox = ["nym-sphinx-types/outfox"]
sphinx = ["nym-crypto/sphinx", "nym-sphinx-types/outfox"]
outfox = ["nym-crypto/outfox", "nym-sphinx-types/outfox"]
+7 -17
View File
@@ -1,22 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::{array::TryFromSliceError, fmt};
use thiserror::Error;
#[cfg(feature = "outfox")]
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
#[cfg(feature = "sphinx")]
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
#[cfg(feature = "outfox")]
pub use nym_outfox::{
constants::MIN_PACKET_SIZE, constants::MIX_PARAMS_LEN, constants::OUTFOX_PACKET_OVERHEAD,
error::OutfoxError,
};
// re-exporting types and constants available in sphinx
#[cfg(feature = "outfox")]
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
#[cfg(feature = "sphinx")]
pub use sphinx_packet::{
constants::{
@@ -29,10 +21,12 @@ pub use sphinx_packet::{
payload::{Payload, PAYLOAD_OVERHEAD_SIZE},
route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier},
surb::{SURBMaterial, SURB},
version::Version,
version::UPDATED_LEGACY_VERSION,
Error as SphinxError, ProcessedPacket, ProcessedPacketData,
Error as SphinxError, ProcessedPacket,
};
#[cfg(feature = "sphinx")]
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
use std::{array::TryFromSliceError, fmt};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum NymPacketError {
@@ -91,12 +85,8 @@ impl NymPacket {
destination: &Destination,
delays: &[Delay],
) -> Result<NymPacket, NymPacketError> {
// FIXME:
// for now explicitly use the legacy version until sufficient number of nodes
// understand both variants
Ok(NymPacket::Sphinx(
SphinxPacketBuilder::new()
.with_version(UPDATED_LEGACY_VERSION)
.with_payload_size(size)
.build_packet(message, route, destination, delays)?,
))
+1 -1
View File
@@ -27,7 +27,7 @@ wasm-bindgen = { workspace = true, optional = true }
## internal
nym-config = { path = "../config" }
nym-crypto = { path = "../crypto" }
nym-crypto = { path = "../crypto", features = ["sphinx", "outfox"] }
nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
nym-sphinx-addressing = { path = "../nymsphinx/addressing" }
nym-sphinx-types = { path = "../nymsphinx/types", features = [
+1 -1
View File
@@ -105,7 +105,7 @@ impl<'a> From<&'a RoutingNode> for SphinxNode {
.try_into()
.unwrap();
SphinxNode::new(node_address_bytes, node.sphinx_key.into())
SphinxNode::new(node_address_bytes, (&node.sphinx_key).into())
}
}
+337 -150
View File
File diff suppressed because it is too large Load Diff
-7
View File
@@ -1,7 +0,0 @@
{
"git": {
"deploymentEnabled": {
"master": false
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "explorer-api"
version = "1.1.46"
version = "1.1.47"
edition = "2021"
license.workspace = true
+1 -1
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-api"
license = "GPL-3.0"
version = "1.1.50"
version = "1.1.51"
authors.workspace = true
edition = "2021"
rust-version.workspace = true
@@ -3,7 +3,7 @@
[package]
name = "nym-node-status-agent"
version = "1.0.0-rc.2"
version = "1.0.0-rc.1"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
@@ -1,9 +1,9 @@
#!/bin/bash
set -eu
export ENVIRONMENT=${ENVIRONMENT:-"mainnet"}
export ENVIRONMENT=${ENVIRONMENT:-"sandbox"}
probe_git_ref="nym-vpn-core-v1.3.2"
probe_git_ref="nym-vpn-core-v1.1.0"
crate_root=$(dirname $(realpath "$0"))
monorepo_root=$(realpath "${crate_root}/../..")
@@ -21,7 +21,6 @@ export NODE_STATUS_AGENT_SERVER_ADDRESS="http://127.0.0.1"
export NODE_STATUS_AGENT_SERVER_PORT="8000"
export NODE_STATUS_AGENT_PROBE_PATH="$crate_root/nym-gateway-probe"
export NODE_STATUS_AGENT_AUTH_KEY="BjyC9SsHAZUzPRkQR4sPTvVrp4GgaquTh5YfSJksvvWT"
export NODE_STATUS_AGENT_PROBE_EXTRA_ARGS="netstack-download-timeout-sec=30,netstack-num-ping=2,netstack-send-timeout-sec=1,netstack-recv-timeout-sec=1"
workers=${1:-1}
echo "Running $workers workers in parallel"
@@ -55,7 +54,7 @@ function swarm() {
echo "All agents completed"
}
copy_gw_probe
# copy_gw_probe
build_agent
swarm $workers
@@ -35,13 +35,6 @@ pub(crate) enum Command {
/// path of binary to run
#[arg(long, env = "NODE_STATUS_AGENT_PROBE_PATH")]
probe_path: String,
#[arg(
long,
env = "NODE_STATUS_AGENT_PROBE_EXTRA_ARGS",
value_delimiter = ','
)]
probe_extra_args: Vec<String>,
},
GenerateKeypair {
@@ -58,13 +51,11 @@ impl Args {
server_port,
ns_api_auth_key,
probe_path,
probe_extra_args,
} => run_probe::run_probe(
server_address,
server_port.to_owned(),
ns_api_auth_key,
probe_path,
probe_extra_args,
)
.await
.inspect_err(|err| {
@@ -7,7 +7,6 @@ pub(crate) async fn run_probe(
server_port: u16,
ns_api_auth_key: &str,
probe_path: &str,
probe_extra_args: &Vec<String>,
) -> anyhow::Result<()> {
let auth_key = PrivateKey::from_base58_string(ns_api_auth_key)
.context("Couldn't parse auth key, exiting")?;
@@ -20,7 +19,7 @@ pub(crate) async fn run_probe(
tracing::info!("Probe version:\n{}", version);
if let Some(testrun) = ns_api_client.request_testrun().await? {
let log = probe.run_and_get_log(&Some(testrun.gateway_identity_key), probe_extra_args);
let log = probe.run_and_get_log(&Some(testrun.gateway_identity_key));
ns_api_client
.submit_results(testrun.testrun_id, log, testrun.assigned_at_utc)
@@ -29,11 +29,7 @@ impl GwProbe {
}
}
pub(crate) fn run_and_get_log(
&self,
gateway_key: &Option<String>,
probe_extra_args: &Vec<String>,
) -> String {
pub(crate) fn run_and_get_log(&self, gateway_key: &Option<String>) -> String {
let mut command = std::process::Command::new(&self.path);
command.stdout(std::process::Stdio::piped());
@@ -41,16 +37,6 @@ impl GwProbe {
command.arg("--gateway").arg(gateway_id);
}
tracing::info!("Extra args for the probe:");
for arg in probe_extra_args {
let mut split = arg.splitn(2, '=');
let name = split.next().unwrap_or_default();
let value = split.next().unwrap_or_default();
tracing::info!("{} {}", name, value);
command.arg(format!("--{name}")).arg(value);
}
match command.spawn() {
Ok(child) => {
if let Ok(output) = child.wait_with_output() {
@@ -3,7 +3,7 @@
set -e
user_rust_log_preference=$RUST_LOG
export ENVIRONMENT=${ENVIRONMENT:-"mainnet"}
export ENVIRONMENT=${ENVIRONMENT:-"sandbox"}
export NYM_API_CLIENT_TIMEOUT=60
export EXPLORER_CLIENT_TIMEOUT=60
export NODE_STATUS_API_TESTRUN_REFRESH_INTERVAL=120
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-node"
version = "1.5.0"
version = "1.6.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
+2 -31
View File
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
use dashmap::DashMap;
use std::fmt::Display;
use std::net::{IpAddr, SocketAddr};
use std::sync::atomic::{AtomicI64, AtomicUsize, Ordering};
use time::OffsetDateTime;
@@ -53,7 +52,7 @@ impl MixingStats {
self.ingress.senders.entry(source).or_default().malformed += 1;
}
pub fn ingress_received_forward_packet(&self, source: IpAddr, version: PacketKind) {
pub fn ingress_received_forward_packet(&self, source: IpAddr) {
self.ingress
.forward_hop_packets_received
.fetch_add(1, Ordering::Relaxed);
@@ -63,10 +62,9 @@ impl MixingStats {
.or_default()
.forward_packets
.received += 1;
*self.ingress.received_versions.entry(version).or_default() += 1;
}
pub fn ingress_received_final_hop_packet(&self, source: IpAddr, version: PacketKind) {
pub fn ingress_received_final_hop_packet(&self, source: IpAddr) {
self.ingress
.final_hop_packets_received
.fetch_add(1, Ordering::Relaxed);
@@ -76,7 +74,6 @@ impl MixingStats {
.or_default()
.final_hop_packets
.received += 1;
*self.ingress.received_versions.entry(version).or_default() += 1;
}
pub fn ingress_excessive_delay_packet(&self) {
@@ -199,30 +196,8 @@ pub struct IngressRecipientStats {
pub malformed: usize,
}
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub enum PacketKind {
#[default]
Unknown,
Outfox,
Sphinx(u16),
}
impl Display for PacketKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
PacketKind::Unknown => "unknown".fmt(f),
PacketKind::Outfox => "outfox".fmt(f),
PacketKind::Sphinx(sphinx_version) => {
write!(f, "sphinx-{sphinx_version}")
}
}
}
}
#[derive(Default)]
pub struct IngressMixingStats {
received_versions: DashMap<PacketKind, i64>,
// forward hop packets (i.e. to mixnode)
forward_hop_packets_received: AtomicUsize,
@@ -273,10 +248,6 @@ impl IngressMixingStats {
&self.senders
}
pub fn packet_versions(&self) -> &DashMap<PacketKind, i64> {
&self.received_versions
}
pub fn remove_stale_sender(&self, sender: IpAddr) {
self.senders.remove(&sender);
}
@@ -1,7 +1,6 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::mixnet::PacketKind;
use nym_metrics::{metrics_registry, HistogramTimer, Metric};
use std::sync::LazyLock;
use strum::{Display, EnumCount, EnumIter, EnumProperty, IntoEnumIterator};
@@ -29,10 +28,6 @@ const CLIENT_SESSION_DURATION_BUCKETS: &[f64] = &[
pub enum PrometheusMetric {
// # MIXNET
// ## INGRESS
#[strum(to_string = "mixnet_ingress_packet_version_{kind}")]
#[strum(props(help = "The number of ingress packets received with the particular version"))]
MixnetIngressPacketVersion { kind: PacketKind },
#[strum(props(help = "The number of ingress forward hop sphinx packets received"))]
MixnetIngressForwardPacketsReceived,
@@ -183,11 +178,7 @@ impl PrometheusMetric {
}
fn is_complex(&self) -> bool {
matches!(
self,
PrometheusMetric::EntryClientSessionsDurations { .. }
| PrometheusMetric::MixnetIngressPacketVersion { .. }
)
matches!(self, PrometheusMetric::EntryClientSessionsDurations { .. })
// match self {
// PrometheusMetric::EntryClientSessionsDurations { .. } => true,
// _ => false,
@@ -199,9 +190,6 @@ impl PrometheusMetric {
let help = self.help();
match self {
PrometheusMetric::MixnetIngressPacketVersion { .. } => {
Metric::new_int_gauge(&name, help)
}
PrometheusMetric::MixnetIngressForwardPacketsReceived => {
Metric::new_int_gauge(&name, help)
}
@@ -376,7 +364,7 @@ mod tests {
// a sanity check for anyone adding new metrics. if this test fails,
// make sure any methods on `PrometheusMetric` enum don't need updating
// or require custom Display impl
assert_eq!(38, PrometheusMetric::COUNT)
assert_eq!(37, PrometheusMetric::COUNT)
}
#[test]
@@ -397,24 +385,6 @@ mod tests {
assert_eq!(
"nym_node_entry_client_sessions_durations_vpn",
parameterised
);
let parameterised = PrometheusMetric::MixnetIngressPacketVersion {
kind: PacketKind::Outfox,
}
.to_string();
assert_eq!(
"nym_node_mixnet_ingress_packet_version_outfox",
parameterised
);
let parameterised = PrometheusMetric::MixnetIngressPacketVersion {
kind: PacketKind::Sphinx(42),
}
.to_string();
assert_eq!(
"nym_node_mixnet_ingress_packet_version_sphinx-42",
parameterised
);
)
}
}
@@ -43,15 +43,6 @@ impl OnUpdateMetricsHandler for PrometheusGlobalNodeMetricsRegistryUpdater {
// # MIXNET
// ## INGRESS
for version_entry in self.metrics.mixnet.ingress.packet_versions() {
self.prometheus_wrapper.set(
MixnetIngressPacketVersion {
kind: *version_entry.key(),
},
*version_entry.value(),
)
}
self.prometheus_wrapper.set(
MixnetIngressForwardPacketsReceived,
self.metrics.mixnet.ingress.forward_hop_packets_received() as i64,
+9 -12
View File
@@ -8,7 +8,7 @@ use nym_sphinx_forwarding::packet::MixPacket;
use nym_sphinx_framing::codec::NymCodec;
use nym_sphinx_framing::packet::FramedNymPacket;
use nym_sphinx_framing::processing::{
process_framed_packet, MixProcessingResultData, ProcessedFinalHop,
process_framed_packet, MixProcessingResult, ProcessedFinalHop,
};
use nym_sphinx_types::Delay;
use std::net::SocketAddr;
@@ -44,7 +44,7 @@ impl ConnectionHandler {
ConnectionHandler {
shared: SharedData {
processing_config: shared.processing_config,
sphinx_keys: shared.sphinx_keys.clone(),
sphinx_key: shared.sphinx_key.clone(),
mixnet_forwarder: shared.mixnet_forwarder.clone(),
final_hop: shared.final_hop.clone(),
metrics: shared.metrics.clone(),
@@ -135,8 +135,7 @@ impl ConnectionHandler {
nanos!("handle_received_nym_packet", {
// 1. attempt to unwrap the packet
let unwrapped_packet =
process_framed_packet(packet, self.shared.sphinx_keys.private_key().as_ref());
let unwrapped_packet = process_framed_packet(packet, &self.shared.sphinx_key);
// 2. increment our favourite metrics stats
self.shared
@@ -145,14 +144,12 @@ impl ConnectionHandler {
// 3. forward the packet to the relevant sink (if enabled)
match unwrapped_packet {
Err(err) => trace!("failed to process received mix packet: {err}"),
Ok(processed_packet) => match processed_packet.processing_data {
MixProcessingResultData::ForwardHop { packet, delay } => {
self.handle_forward_packet(packet, delay);
}
MixProcessingResultData::FinalHop { final_hop_data } => {
self.handle_final_hop(final_hop_data).await;
}
},
Ok(MixProcessingResult::ForwardHop(forward_packet, delay)) => {
self.handle_forward_packet(forward_packet, delay);
}
Ok(MixProcessingResult::FinalHop(final_hop_data)) => {
self.handle_final_hop(final_hop_data).await;
}
}
})
}
+11 -28
View File
@@ -7,12 +7,9 @@ use crate::node::mixnet::SharedFinalHopData;
use nym_crypto::asymmetric::x25519;
use nym_gateway::node::GatewayStorageError;
use nym_mixnet_client::forwarder::{MixForwardingSender, PacketToForward};
use nym_node_metrics::mixnet::PacketKind;
use nym_node_metrics::NymNodeMetrics;
use nym_sphinx_forwarding::packet::MixPacket;
use nym_sphinx_framing::processing::{
MixPacketVersion, MixProcessingResult, MixProcessingResultData, PacketProcessingError,
};
use nym_sphinx_framing::processing::{MixProcessingResult, PacketProcessingError};
use nym_sphinx_types::DestinationAddressBytes;
use nym_task::ShutdownToken;
use std::io;
@@ -48,7 +45,8 @@ impl ProcessingConfig {
// explicitly do NOT derive clone as we want to manually apply relevant suffixes to the task clients
pub(crate) struct SharedData {
pub(super) processing_config: ProcessingConfig,
pub(super) sphinx_keys: Arc<x25519::KeyPair>,
// TODO: this type is not `Zeroize` : (
pub(super) sphinx_key: Arc<nym_sphinx_types::PrivateKey>,
// used for FORWARD mix packets and FINAL ack packets
pub(super) mixnet_forwarder: MixForwardingSender,
@@ -60,17 +58,10 @@ pub(crate) struct SharedData {
pub(super) shutdown: ShutdownToken,
}
fn convert_to_metrics_version(processed: MixPacketVersion) -> PacketKind {
match processed {
MixPacketVersion::Outfox => PacketKind::Outfox,
MixPacketVersion::Sphinx(sphinx_version) => PacketKind::Sphinx(sphinx_version.value()),
}
}
impl SharedData {
pub(crate) fn new(
processing_config: ProcessingConfig,
x25519_keys: Arc<x25519::KeyPair>,
x25519_key: &x25519::PrivateKey,
mixnet_forwarder: MixForwardingSender,
final_hop: SharedFinalHopData,
metrics: NymNodeMetrics,
@@ -78,7 +69,7 @@ impl SharedData {
) -> Self {
SharedData {
processing_config,
sphinx_keys: x25519_keys,
sphinx_key: Arc::new(x25519_key.into()),
mixnet_forwarder,
final_hop,
metrics,
@@ -108,18 +99,10 @@ impl SharedData {
processing_result: &Result<MixProcessingResult, PacketProcessingError>,
source: IpAddr,
) {
let Ok(processing_result) = processing_result else {
self.metrics.mixnet.ingress_malformed_packet(source);
return;
};
let packet_version = convert_to_metrics_version(processing_result.packet_version);
match processing_result.processing_data {
MixProcessingResultData::ForwardHop { delay, .. } => {
self.metrics
.mixnet
.ingress_received_forward_packet(source, packet_version);
match processing_result {
Err(_) => self.metrics.mixnet.ingress_malformed_packet(source),
Ok(MixProcessingResult::ForwardHop(_, delay)) => {
self.metrics.mixnet.ingress_received_forward_packet(source);
// check if the delay wasn't excessive
if let Some(delay) = delay {
@@ -128,10 +111,10 @@ impl SharedData {
}
}
}
MixProcessingResultData::FinalHop { .. } => {
Ok(MixProcessingResult::FinalHop(_)) => {
self.metrics
.mixnet
.ingress_received_final_hop_packet(source, packet_version);
.ingress_received_final_hop_packet(source);
}
}
}
+1 -1
View File
@@ -993,7 +993,7 @@ impl NymNode {
let shared = mixnet::SharedData::new(
processing_config,
self.x25519_sphinx_keys.clone(),
self.x25519_sphinx_keys.private_key(),
mix_packet_sender.clone(),
final_hop_data,
self.metrics.clone(),
+1 -1
View File
@@ -14,7 +14,7 @@ rayon = { workspace = true }
blake3 = { workspace = true }
zeroize = { workspace = true }
chacha20 = { workspace = true, features = ["std"] }
x25519-dalek = { workspace = true }
curve25519-dalek = { workspace = true }
chacha20poly1305 = { workspace = true }
getrandom = { workspace = true, features = ["js"] }
thiserror = { workspace = true }
+29 -19
View File
@@ -54,6 +54,17 @@
//! routing data for the layer, and the remaining Header; separately the master key is used to lion encrypt
//! the payload. The process is repeated for each layer (from last to first) to construct the full message.
use chacha20poly1305::AeadInPlace;
use chacha20poly1305::ChaCha20Poly1305;
use chacha20poly1305::KeyInit;
use chacha20poly1305::Tag;
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
use curve25519_dalek::montgomery::MontgomeryPoint;
use curve25519_dalek::scalar::Scalar;
use std::ops::Range;
use crate::constants::groupelementbytes;
use crate::constants::tagbytes;
use crate::constants::DEFAULT_HOPS;
@@ -64,11 +75,6 @@ use crate::constants::ROUTING_INFORMATION_LENGTH_BY_STAGE;
use crate::constants::TAGBYTES;
use crate::error::OutfoxError;
use crate::lion::*;
use chacha20poly1305::AeadInPlace;
use chacha20poly1305::ChaCha20Poly1305;
use chacha20poly1305::KeyInit;
use chacha20poly1305::Tag;
use std::ops::Range;
/// A structure that holds mix packet construction parameters. These incluse the length
/// of the routing information at each hop, the number of hops, and the payload length.
@@ -212,11 +218,13 @@ impl MixStageParameters {
pub fn encode_mix_layer(
&self,
buffer: &mut [u8],
user_secret_key: &x25519_dalek::StaticSecret,
mix_public_key: x25519_dalek::PublicKey,
user_secret_key: &[u8],
node_pub_key: &[u8],
destination: &[u8; 32],
) -> Result<x25519_dalek::SharedSecret, OutfoxError> {
) -> Result<MontgomeryPoint, OutfoxError> {
let routing_data = destination;
let mix_public_key = MontgomeryPoint(node_pub_key.try_into()?);
let user_secret_key = Scalar::from_bytes_mod_order(user_secret_key.try_into()?);
if buffer.len() != self.incoming_packet_length() {
return Err(OutfoxError::LenMismatch {
@@ -232,14 +240,14 @@ impl MixStageParameters {
});
}
let user_public_key = x25519_dalek::PublicKey::from(user_secret_key);
let shared_key = user_secret_key.diffie_hellman(&mix_public_key);
let user_public_key = (ED25519_BASEPOINT_TABLE * &user_secret_key).to_montgomery();
let shared_key = user_secret_key * mix_public_key;
// Copy rounting data into buffer
buffer[self.routing_data_range()].copy_from_slice(routing_data);
// Perform the AEAD
let header_aead_key = ChaCha20Poly1305::new_from_slice(shared_key.as_bytes())?;
let header_aead_key = ChaCha20Poly1305::new_from_slice(&shared_key.0[..])?;
let nonce = [0u8; 12];
let tag = header_aead_key
@@ -250,10 +258,10 @@ impl MixStageParameters {
buffer[self.tag_range()].copy_from_slice(&tag[..]);
// Copy own public key into buffer
buffer[self.pub_element_range()].copy_from_slice(user_public_key.as_bytes());
buffer[self.pub_element_range()].copy_from_slice(&user_public_key.0[..]);
// Do a round of LION on the payload
lion_transform_encrypt(&mut buffer[self.payload_range()], shared_key.as_bytes())?;
lion_transform_encrypt(&mut buffer[self.payload_range()], &shared_key.0)?;
Ok(shared_key)
}
@@ -261,9 +269,12 @@ impl MixStageParameters {
pub fn decode_mix_layer(
&self,
buffer: &mut [u8],
mix_secret_key: &x25519_dalek::StaticSecret,
mix_secret_key: &[u8],
) -> Result<Vec<u8>, OutfoxError> {
// Check the length of the incoming buffer is correct.
let mix_secret_key = Scalar::from_bytes_mod_order(mix_secret_key.try_into()?);
if buffer.len() != self.incoming_packet_length() {
return Err(OutfoxError::LenMismatch {
expected: buffer.len(),
@@ -272,12 +283,11 @@ impl MixStageParameters {
}
// Derive the shared key for this packet
let user_public_key_bytes: [u8; 32] = buffer[self.pub_element_range()].try_into()?;
let user_public_key = x25519_dalek::PublicKey::from(user_public_key_bytes);
let shared_key = mix_secret_key.diffie_hellman(&user_public_key);
let user_public_key = MontgomeryPoint(buffer[self.pub_element_range()].try_into()?);
let shared_key = mix_secret_key * user_public_key;
// Compute the AEAD and check the Tag, if wrong return Err
let header_aead_key = ChaCha20Poly1305::new_from_slice(shared_key.as_bytes())?;
let header_aead_key = ChaCha20Poly1305::new_from_slice(&shared_key.0[..])?;
let nonce = [0; 12];
let tag_bytes = buffer[self.tag_range()].to_vec();
@@ -294,7 +304,7 @@ impl MixStageParameters {
let routing_data = buffer[self.routing_data_range()].to_vec();
// Do a round of LION on the payload
lion_transform_decrypt(&mut buffer[self.payload_range()], shared_key.as_bytes())?;
lion_transform_decrypt(&mut buffer[self.payload_range()], &shared_key.0)?;
Ok(routing_data)
}
+12 -7
View File
@@ -1,14 +1,17 @@
use std::{array::TryFromSliceError, collections::VecDeque, ops::Range};
use crate::{
constants::{DEFAULT_HOPS, MAGIC_SLICE, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
error::OutfoxError,
format::{MixCreationParameters, MixStageParameters},
};
use rand::{rngs::OsRng, RngCore};
use sphinx_packet::{
crypto::PrivateKey,
packet::builder::DEFAULT_PAYLOAD_SIZE,
route::{Destination, Node},
};
use std::{array::TryFromSliceError, collections::VecDeque, ops::Range};
#[derive(Debug)]
pub struct OutfoxPacket {
@@ -87,7 +90,8 @@ impl OutfoxPacket {
destination: &Destination,
packet_size: Option<usize>,
) -> Result<OutfoxPacket, OutfoxError> {
let secret_key = x25519_dalek::StaticSecret::random();
let mut secret_key = [0; 32];
OsRng.fill_bytes(&mut secret_key);
let packet_size = packet_size.unwrap_or(DEFAULT_PAYLOAD_SIZE);
let packet_size = if packet_size < MIN_PACKET_SIZE {
MIN_PACKET_SIZE
@@ -106,7 +110,7 @@ impl OutfoxPacket {
stage_params.encode_mix_layer(
&mut buffer[range],
&secret_key,
route.last().unwrap().pub_key,
route.last().unwrap().pub_key.as_bytes(),
destination.address.as_bytes_ref(),
)?;
@@ -126,11 +130,11 @@ impl OutfoxPacket {
// We know that we'll always get 4 nodes, so we can unwrap here
let processing_node = nodes.last().unwrap();
let destination_node = nodes.first().unwrap();
let secret_key = x25519_dalek::StaticSecret::random();
OsRng.fill_bytes(&mut secret_key);
stage_params.encode_mix_layer(
&mut buffer[range],
&secret_key,
processing_node.pub_key,
processing_node.pub_key.as_bytes(),
destination_node.address.as_bytes_ref(),
)?;
}
@@ -164,7 +168,7 @@ impl OutfoxPacket {
pub fn decode_mix_layer(
&mut self,
layer: usize,
mix_secret_key: &x25519_dalek::StaticSecret,
mix_secret_key: &[u8; 32],
) -> Result<Vec<u8>, OutfoxError> {
let (range, params) = self.stage_params(layer);
let routing_data =
@@ -194,6 +198,7 @@ impl OutfoxPacket {
&mut self,
mix_secret_key: &PrivateKey,
) -> Result<[u8; 32], OutfoxError> {
let mix_secret_key = mix_secret_key.to_bytes();
let routing_lenght_by_stage = self
.mix_params()
.routing_information_length_by_stage
@@ -205,7 +210,7 @@ impl OutfoxPacket {
break;
}
}
self.decode_mix_layer(layer, mix_secret_key)?;
self.decode_mix_layer(layer, &mix_secret_key)?;
self.update_routing_information(layer)?;
let (range, stage_params) = self.mix_params().get_stage_params(layer);
let routing_bytes = &self.payload()[range][stage_params.routing_data_range()];
+17 -19
View File
@@ -9,9 +9,11 @@ mod tests {
repeat_with(|| fastrand::u8(..)).take(n).collect()
}
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
use curve25519_dalek::scalar::Scalar;
use nym_outfox::packet::OutfoxPacket;
use sphinx_packet::constants::NODE_ADDRESS_LENGTH;
use sphinx_packet::crypto::{PrivateKey, PublicKey};
use sphinx_packet::crypto::PublicKey;
use sphinx_packet::route::Destination;
use sphinx_packet::route::DestinationAddressBytes;
use sphinx_packet::route::Node;
@@ -20,12 +22,6 @@ mod tests {
use nym_outfox::format::*;
use nym_outfox::lion::*;
pub fn keygen() -> (PrivateKey, PublicKey) {
let private_key = PrivateKey::random();
let public_key = PublicKey::from(&private_key);
(private_key, public_key)
}
#[test]
fn test_encode_decode() {
let mix_params = MixStageParameters {
@@ -34,9 +30,11 @@ mod tests {
payload_length_bytes: 1024, // 1kb
};
let user_secret = x25519_dalek::StaticSecret::random();
let mix_secret = x25519_dalek::StaticSecret::random();
let mix_public_key = x25519_dalek::PublicKey::from(&mix_secret);
let user_secret = randombytes(32);
let mix_secret = randombytes(32);
let mix_secret_scalar =
Scalar::from_bytes_mod_order(mix_secret.clone().try_into().unwrap());
let mix_public_key = (ED25519_BASEPOINT_TABLE * &mix_secret_scalar).to_montgomery();
let routing = [0; 32];
let destination = [0; 32];
@@ -54,7 +52,7 @@ mod tests {
.encode_mix_layer(
&mut new_buffer[..],
&user_secret,
node.pub_key,
node.pub_key.as_bytes(),
&destination,
)
.unwrap();
@@ -95,23 +93,23 @@ mod tests {
#[test]
fn test_packet_params_short() {
let (node1_pk, node1_pub) = keygen();
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
node1_pub,
);
let (node2_pk, node2_pub) = keygen();
let (node2_pk, node2_pub) = sphinx_packet::crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([1u8; NODE_ADDRESS_LENGTH]),
node2_pub,
);
let (node3_pk, node3_pub) = keygen();
let (node3_pk, node3_pub) = sphinx_packet::crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pub,
);
let (gateway_pk, gateway_pub) = keygen();
let (gateway_pk, gateway_pub) = sphinx_packet::crypto::keygen();
let gateway = Node::new(
NodeAddressBytes::from_bytes([3u8; NODE_ADDRESS_LENGTH]),
gateway_pub,
@@ -151,23 +149,23 @@ mod tests {
#[test]
fn test_packet_params_long() {
let (node1_pk, node1_pub) = keygen();
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
node1_pub,
);
let (node2_pk, node2_pub) = keygen();
let (node2_pk, node2_pub) = sphinx_packet::crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([1u8; NODE_ADDRESS_LENGTH]),
node2_pub,
);
let (node3_pk, node3_pub) = keygen();
let (node3_pk, node3_pub) = sphinx_packet::crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pub,
);
let (gateway_pk, gateway_pub) = keygen();
let (gateway_pk, gateway_pub) = sphinx_packet::crypto::keygen();
let gateway = Node::new(
NodeAddressBytes::from_bytes([3u8; NODE_ADDRESS_LENGTH]),
gateway_pub,
+178 -34
View File
@@ -30,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
"crypto-common",
"generic-array",
"generic-array 0.14.7",
]
[[package]]
@@ -55,7 +55,7 @@ dependencies = [
"cipher",
"ctr",
"ghash",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -154,11 +154,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2e554a8638bdc1e4eae9984845306cc95f8a9208ba8d49c3859fd958b46774d"
dependencies = [
"base64ct",
"blake2",
"blake2 0.10.6",
"cpufeatures",
"password-hash",
]
[[package]]
name = "arrayref"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]]
name = "async-compression"
version = "0.4.18"
@@ -313,7 +319,7 @@ dependencies = [
"ripemd",
"secp256k1",
"sha2 0.10.8",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -349,6 +355,18 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "blake2"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330"
dependencies = [
"byte-tools",
"crypto-mac",
"digest 0.8.1",
"opaque-debug 0.2.3",
]
[[package]]
name = "blake2"
version = "0.10.6"
@@ -370,7 +388,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
"generic-array 0.14.7",
]
[[package]]
@@ -379,7 +397,7 @@ version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
"generic-array 0.14.7",
]
[[package]]
@@ -394,7 +412,7 @@ dependencies = [
"rand_core 0.6.4",
"serde",
"serdect 0.3.0-pre.0",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -451,6 +469,12 @@ version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "bytemuck"
version = "1.13.1"
@@ -597,6 +621,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862"
dependencies = [
"byteorder",
"keystream",
]
[[package]]
name = "cipher"
version = "0.4.4"
@@ -951,9 +985,9 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
dependencies = [
"generic-array",
"generic-array 0.14.7",
"rand_core 0.6.4",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -963,11 +997,21 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"generic-array 0.14.7",
"rand_core 0.6.4",
"typenum",
]
[[package]]
name = "crypto-mac"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
dependencies = [
"generic-array 0.12.4",
"subtle 1.0.0",
]
[[package]]
name = "cssparser"
version = "0.27.2"
@@ -1023,7 +1067,7 @@ dependencies = [
"byteorder",
"digest 0.9.0",
"rand_core 0.5.1",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -1041,7 +1085,7 @@ dependencies = [
"platforms",
"rustc_version",
"serde",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -1251,13 +1295,22 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array 0.12.4",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
"generic-array 0.14.7",
]
[[package]]
@@ -1269,7 +1322,7 @@ dependencies = [
"block-buffer 0.10.4",
"const-oid",
"crypto-common",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -1434,7 +1487,7 @@ dependencies = [
"rand_core 0.6.4",
"serde",
"sha2 0.10.8",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -1469,13 +1522,13 @@ dependencies = [
"crypto-bigint",
"digest 0.10.7",
"ff",
"generic-array",
"generic-array 0.14.7",
"group",
"pkcs8",
"rand_core 0.6.4",
"sec1",
"serdect 0.2.0",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -1588,7 +1641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"rand_core 0.6.4",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -1868,6 +1921,15 @@ dependencies = [
"windows 0.48.0",
]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1921,7 +1983,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"opaque-debug 0.3.0",
"polyval",
]
@@ -2044,7 +2106,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand_core 0.6.4",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -2272,6 +2334,15 @@ dependencies = [
"webpki-roots 0.25.4",
]
[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
@@ -2754,7 +2825,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
"generic-array 0.14.7",
]
[[package]]
@@ -2911,6 +2982,12 @@ dependencies = [
"signature",
]
[[package]]
name = "keystream"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28"
[[package]]
name = "kuchiki"
version = "0.8.1"
@@ -2935,6 +3012,12 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "line-wrap"
version = "0.1.1"
@@ -2956,6 +3039,18 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
[[package]]
name = "lioness"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae926706ba42c425c9457121178330d75e273df2e82e28b758faf3de3a9acb9"
dependencies = [
"arrayref",
"blake2 0.8.1",
"chacha",
"keystream",
]
[[package]]
name = "litemap"
version = "0.7.4"
@@ -3226,6 +3321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
"libm",
]
[[package]]
@@ -3340,7 +3436,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"sha2 0.9.9",
"subtle",
"subtle 2.5.0",
"thiserror 2.0.11",
"zeroize",
]
@@ -3561,6 +3657,7 @@ dependencies = [
name = "nym-sphinx-types"
version = "0.2.0"
dependencies = [
"sphinx-packet",
"thiserror 2.0.11",
]
@@ -3570,7 +3667,7 @@ version = "0.1.0"
dependencies = [
"aes-gcm",
"argon2",
"generic-array",
"generic-array 0.14.7",
"getrandom 0.2.10",
"rand 0.8.5",
"serde",
@@ -3836,6 +3933,12 @@ version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "opaque-debug"
version = "0.3.0"
@@ -3973,7 +4076,7 @@ checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core 0.6.4",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -4263,7 +4366,7 @@ checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"opaque-debug 0.3.0",
"universal-hash",
]
@@ -4514,6 +4617,16 @@ dependencies = [
"getrandom 0.2.10",
]
[[package]]
name = "rand_distr"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
dependencies = [
"num-traits",
"rand 0.8.5",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
@@ -4717,7 +4830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
"hmac",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -4826,7 +4939,7 @@ dependencies = [
"ring",
"rustls-pki-types",
"rustls-webpki 0.102.4",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -4979,10 +5092,10 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
dependencies = [
"base16ct",
"der",
"generic-array",
"generic-array 0.14.7",
"pkcs8",
"serdect 0.2.0",
"subtle",
"subtle 2.5.0",
"zeroize",
]
@@ -5233,7 +5346,7 @@ dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.9.0",
"opaque-debug",
"opaque-debug 0.3.0",
]
[[package]]
@@ -5350,6 +5463,31 @@ dependencies = [
"system-deps 5.0.0",
]
[[package]]
name = "sphinx-packet"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dabeca95bf5fd0563d6be7ebcb1c6a9fcb135746a0ba9050c47dc68c8607e595"
dependencies = [
"aes",
"arrayref",
"blake2 0.8.1",
"bs58",
"byteorder",
"chacha",
"ctr",
"curve25519-dalek 4.1.2",
"digest 0.10.7",
"hkdf",
"hmac",
"lioness",
"log",
"rand 0.8.5",
"rand_distr",
"sha2 0.10.8",
"subtle 2.5.0",
]
[[package]]
name = "spin"
version = "0.9.8"
@@ -5457,6 +5595,12 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "subtle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
[[package]]
name = "subtle"
version = "2.5.0"
@@ -5847,7 +5991,7 @@ dependencies = [
"serde_repr",
"sha2 0.10.8",
"signature",
"subtle",
"subtle 2.5.0",
"subtle-encoding",
"tendermint-proto 0.34.0",
"time",
@@ -5877,7 +6021,7 @@ dependencies = [
"serde_repr",
"sha2 0.10.8",
"signature",
"subtle",
"subtle 2.5.0",
"subtle-encoding",
"tendermint-proto 0.40.1",
"time",
@@ -5950,7 +6094,7 @@ dependencies = [
"serde",
"serde_bytes",
"serde_json",
"subtle",
"subtle 2.5.0",
"subtle-encoding",
"tendermint 0.40.1",
"tendermint-config",
@@ -6414,7 +6558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle",
"subtle 2.5.0",
]
[[package]]
@@ -4,7 +4,7 @@
[package]
name = "nym-network-requester"
license = "GPL-3.0"
version = "1.1.49"
version = "1.1.50"
authors.workspace = true
edition.workspace = true
rust-version = "1.70"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-cli"
version = "1.1.48"
version = "1.1.49"
authors.workspace = true
edition = "2021"
license.workspace = true
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nymvisor"
version = "0.1.13"
version = "0.1.14"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
@@ -156,3 +156,15 @@ pub struct UnblindableShare {
pub issuer_key_bs58: String,
pub blinded_share_bs58: String,
}
#[wasm_bindgen]
impl UnblindableShare {
#[wasm_bindgen(constructor)]
pub fn new(issuer_index: u64, issuer_key_bs58: String, blinded_share_bs58: String) -> Self {
UnblindableShare {
issuer_index,
issuer_key_bs58,
blinded_share_bs58,
}
}
}