further propagation of key rotation information
This commit is contained in:
@@ -21,8 +21,8 @@ use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_requests::registration::handshake::client_handshake;
|
||||
use nym_gateway_requests::{
|
||||
BinaryRequest, ClientControlRequest, ClientRequest, GatewayProtocolVersionExt,
|
||||
SensitiveServerResponse, ServerResponse, SharedGatewayKey, SharedSymmetricKey,
|
||||
CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
|
||||
GatewayRequestsError, SensitiveServerResponse, ServerResponse, SharedGatewayKey,
|
||||
SharedSymmetricKey, CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
|
||||
};
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_statistics_common::clients::connection::ConnectionStatsEvent;
|
||||
@@ -662,6 +662,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
let supports_aes_gcm_siv = gw_protocol.supports_aes256_gcm_siv();
|
||||
let supports_auth_v2 = gw_protocol.supports_authenticate_v2();
|
||||
let supports_key_rotation_info = gw_protocol.supports_key_rotation_packet();
|
||||
|
||||
if !supports_aes_gcm_siv {
|
||||
warn!("this gateway is on an old version that doesn't support AES256-GCM-SIV");
|
||||
@@ -669,6 +670,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
if !supports_auth_v2 {
|
||||
warn!("this gateway is on an old version that doesn't support authentication v2")
|
||||
}
|
||||
if !supports_key_rotation_info {
|
||||
warn!("this gateway is on an old version that doesn't support key rotation packets")
|
||||
}
|
||||
|
||||
if self.authenticated {
|
||||
debug!("Already authenticated");
|
||||
@@ -849,6 +853,22 @@ impl<C, St> GatewayClient<C, St> {
|
||||
}
|
||||
}
|
||||
|
||||
fn mix_packet_to_ws_message(&self, packet: MixPacket) -> Result<Message, GatewayRequestsError> {
|
||||
// note: into_ws_message encrypts the requests and adds a MAC on it. Perhaps it should
|
||||
// be more explicit in the naming?
|
||||
let req = if self.negotiated_protocol.supports_key_rotation_packet() {
|
||||
BinaryRequest::ForwardSphinxV2 { packet }
|
||||
} else {
|
||||
BinaryRequest::ForwardSphinx { packet }
|
||||
};
|
||||
|
||||
req.into_ws_message(
|
||||
self.shared_key
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn batch_send_mix_packets(
|
||||
&mut self,
|
||||
packets: Vec<MixPacket>,
|
||||
@@ -877,13 +897,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
let messages: Result<Vec<_>, _> = packets
|
||||
.into_iter()
|
||||
.map(|mix_packet| {
|
||||
BinaryRequest::ForwardSphinx { packet: mix_packet }.into_ws_message(
|
||||
self.shared_key
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
)
|
||||
})
|
||||
.map(|mix_packet| self.mix_packet_to_ws_message(mix_packet))
|
||||
.collect();
|
||||
|
||||
if let Err(err) = self
|
||||
@@ -949,13 +963,8 @@ impl<C, St> GatewayClient<C, St> {
|
||||
if !self.connection.is_established() {
|
||||
return Err(GatewayClientError::ConnectionNotEstablished);
|
||||
}
|
||||
// note: into_ws_message encrypts the requests and adds a MAC on it. Perhaps it should
|
||||
// be more explicit in the naming?
|
||||
let msg = BinaryRequest::ForwardSphinx { packet: mix_packet }.into_ws_message(
|
||||
self.shared_key
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
)?;
|
||||
|
||||
let msg = self.mix_packet_to_ws_message(mix_packet)?;
|
||||
self.send_with_reconnection_on_failure(msg).await
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
use dashmap::DashMap;
|
||||
use futures::StreamExt;
|
||||
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::framing::codec::NymCodec;
|
||||
use nym_sphinx::framing::packet::FramedNymPacket;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_sphinx::NymPacket;
|
||||
use nym_sphinx::params::SphinxKeyRotation;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::ops::Deref;
|
||||
@@ -49,12 +48,7 @@ impl Config {
|
||||
pub trait SendWithoutResponse {
|
||||
// Without response in this context means we will not listen for anything we might get back (not
|
||||
// that we should get anything), including any possible io errors
|
||||
fn send_without_response(
|
||||
&self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
) -> io::Result<()>;
|
||||
fn send_without_response(&self, packet: MixPacket) -> io::Result<()>;
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
@@ -65,7 +59,7 @@ pub struct Client {
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ActiveConnections {
|
||||
inner: Arc<DashMap<NymNodeRoutingAddress, ConnectionSender>>,
|
||||
inner: Arc<DashMap<SocketAddr, ConnectionSender>>,
|
||||
}
|
||||
|
||||
impl ActiveConnections {
|
||||
@@ -82,7 +76,7 @@ impl ActiveConnections {
|
||||
}
|
||||
|
||||
impl Deref for ActiveConnections {
|
||||
type Target = DashMap<NymNodeRoutingAddress, ConnectionSender>;
|
||||
type Target = DashMap<SocketAddr, ConnectionSender>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
@@ -196,7 +190,7 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_connection(&self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
|
||||
fn make_connection(&self, address: SocketAddr, pending_packet: FramedNymPacket) {
|
||||
let (sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
|
||||
|
||||
// this CAN'T fail because we just created the channel which has a non-zero capacity
|
||||
@@ -233,7 +227,7 @@ impl Client {
|
||||
|
||||
connections_count.fetch_add(1, Ordering::SeqCst);
|
||||
ManagedConnection::new(
|
||||
address.into(),
|
||||
address,
|
||||
receiver,
|
||||
initial_connection_timeout,
|
||||
current_reconnection_attempt,
|
||||
@@ -246,18 +240,14 @@ impl Client {
|
||||
}
|
||||
|
||||
impl SendWithoutResponse for Client {
|
||||
fn send_without_response(
|
||||
&self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
) -> io::Result<()> {
|
||||
trace!("Sending packet to {address:?}");
|
||||
let framed_packet = FramedNymPacket::new(packet, packet_type);
|
||||
fn send_without_response(&self, packet: MixPacket) -> io::Result<()> {
|
||||
let address = packet.next_hop_address();
|
||||
trace!("Sending packet to {address}");
|
||||
let framed_packet = FramedNymPacket::from(packet);
|
||||
|
||||
let Some(sender) = self.active_connections.get_mut(&address) else {
|
||||
// there was never a connection to begin with
|
||||
debug!("establishing initial connection to {}", address);
|
||||
debug!("establishing initial connection to {address}");
|
||||
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
|
||||
// for sending for as soon as the connection is created
|
||||
self.make_connection(address, framed_packet);
|
||||
|
||||
@@ -19,7 +19,7 @@ pub use shared_key::{
|
||||
SharedGatewayKey, SharedKeyConversionError, SharedKeyUsageError, SharedSymmetricKey,
|
||||
};
|
||||
|
||||
pub const CURRENT_PROTOCOL_VERSION: u8 = AUTHENTICATE_V2_PROTOCOL_VERSION;
|
||||
pub const CURRENT_PROTOCOL_VERSION: u8 = EMBEDDED_KEY_ROTATION_INFO_VERSION;
|
||||
|
||||
/// Defines the current version of the communication protocol between gateway and clients.
|
||||
/// It has to be incremented for any breaking change.
|
||||
@@ -28,10 +28,12 @@ pub const CURRENT_PROTOCOL_VERSION: u8 = AUTHENTICATE_V2_PROTOCOL_VERSION;
|
||||
// 2 - changes to client credentials structure
|
||||
// 3 - change to AES-GCM-SIV and non-zero IVs
|
||||
// 4 - introduction of v2 authentication protocol to prevent reply attacks
|
||||
// 5 - add key rotation information to the serialised mix packet
|
||||
pub const INITIAL_PROTOCOL_VERSION: u8 = 1;
|
||||
pub const CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION: u8 = 2;
|
||||
pub const AES_GCM_SIV_PROTOCOL_VERSION: u8 = 3;
|
||||
pub const AUTHENTICATE_V2_PROTOCOL_VERSION: u8 = 4;
|
||||
pub const EMBEDDED_KEY_ROTATION_INFO_VERSION: u8 = 5;
|
||||
|
||||
// TODO: could using `Mac` trait here for OutputSize backfire?
|
||||
// Should hmac itself be exposed, imported and used instead?
|
||||
@@ -40,6 +42,7 @@ pub type LegacyGatewayMacSize = <GatewayIntegrityHmacAlgorithm as OutputSizeUser
|
||||
pub trait GatewayProtocolVersionExt {
|
||||
fn supports_aes256_gcm_siv(&self) -> bool;
|
||||
fn supports_authenticate_v2(&self) -> bool;
|
||||
fn supports_key_rotation_packet(&self) -> bool;
|
||||
}
|
||||
|
||||
impl GatewayProtocolVersionExt for Option<u8> {
|
||||
@@ -52,4 +55,9 @@ impl GatewayProtocolVersionExt for Option<u8> {
|
||||
let Some(protocol) = *self else { return false };
|
||||
protocol >= AUTHENTICATE_V2_PROTOCOL_VERSION
|
||||
}
|
||||
|
||||
fn supports_key_rotation_packet(&self) -> bool {
|
||||
let Some(protocol) = *self else { return false };
|
||||
protocol >= EMBEDDED_KEY_ROTATION_INFO_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ use tungstenite::Message;
|
||||
#[non_exhaustive]
|
||||
pub enum BinaryRequest {
|
||||
ForwardSphinx { packet: MixPacket },
|
||||
|
||||
// identical to `ForwardSphinx`, but also contains information about sphinx key rotation used
|
||||
ForwardSphinxV2 { packet: MixPacket },
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
@@ -18,6 +21,9 @@ pub enum BinaryRequest {
|
||||
#[non_exhaustive]
|
||||
pub enum BinaryRequestKind {
|
||||
ForwardSphinx = 1,
|
||||
|
||||
// identical to `ForwardSphinx`, but also contains information about sphinx key rotation used
|
||||
ForwardSphinxV2 = 2,
|
||||
}
|
||||
|
||||
// Right now the only valid `BinaryRequest` is a request to forward a sphinx packet.
|
||||
@@ -29,6 +35,7 @@ impl BinaryRequest {
|
||||
pub fn kind(&self) -> BinaryRequestKind {
|
||||
match self {
|
||||
BinaryRequest::ForwardSphinx { .. } => BinaryRequestKind::ForwardSphinx,
|
||||
BinaryRequest::ForwardSphinxV2 { .. } => BinaryRequestKind::ForwardSphinxV2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +45,13 @@ impl BinaryRequest {
|
||||
) -> Result<Self, GatewayRequestsError> {
|
||||
match kind {
|
||||
BinaryRequestKind::ForwardSphinx => {
|
||||
let packet = MixPacket::try_from_bytes(plaintext)?;
|
||||
let packet = MixPacket::try_from_v1_bytes(plaintext)?;
|
||||
Ok(BinaryRequest::ForwardSphinx { packet })
|
||||
}
|
||||
BinaryRequestKind::ForwardSphinxV2 => {
|
||||
let packet = MixPacket::try_from_v2_bytes(plaintext)?;
|
||||
Ok(BinaryRequest::ForwardSphinxV2 { packet })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +69,8 @@ impl BinaryRequest {
|
||||
let kind = self.kind();
|
||||
|
||||
let plaintext = match self {
|
||||
BinaryRequest::ForwardSphinx { packet } => packet.into_bytes()?,
|
||||
BinaryRequest::ForwardSphinx { packet } => packet.into_v1_bytes()?,
|
||||
BinaryRequest::ForwardSphinxV2 { packet } => packet.into_v2_bytes()?,
|
||||
};
|
||||
|
||||
BinaryData::make_encrypted_blob(kind as u8, &plaintext, shared_key)
|
||||
@@ -70,7 +82,9 @@ impl BinaryRequest {
|
||||
) -> Result<Message, GatewayRequestsError> {
|
||||
// all variants are currently encrypted
|
||||
let blob = match self {
|
||||
BinaryRequest::ForwardSphinx { .. } => self.into_encrypted_tagged_bytes(shared_key)?,
|
||||
BinaryRequest::ForwardSphinx { .. } | BinaryRequest::ForwardSphinxV2 { .. } => {
|
||||
self.into_encrypted_tagged_bytes(shared_key)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Message::Binary(blob))
|
||||
|
||||
@@ -8,7 +8,7 @@ use nym_sphinx_addressing::nodes::{
|
||||
NymNodeRoutingAddress, NymNodeRoutingAddressError, MAX_NODE_ADDRESS_UNPADDED_LEN,
|
||||
};
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm};
|
||||
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, SphinxKeyRotation};
|
||||
use nym_sphinx_types::{
|
||||
NymPacket, SURBMaterial, SphinxError, HEADER_SIZE, NODE_ADDRESS_LENGTH, SURB,
|
||||
X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION,
|
||||
@@ -46,44 +46,7 @@ pub enum ReplySurbError {
|
||||
pub struct ReplySurb {
|
||||
pub(crate) surb: SURB,
|
||||
pub(crate) encryption_key: SurbEncryptionKey,
|
||||
}
|
||||
|
||||
// Serialize + Deserialize is not really used anymore (it was for a CBOR experiment)
|
||||
// however, if we decided we needed it again, it's already here
|
||||
impl Serialize for ReplySurb {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(&self.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ReplySurb {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ReplySurbVisitor;
|
||||
|
||||
impl Visitor<'_> for ReplySurbVisitor {
|
||||
type Value = ReplySurb;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "A replySURB must contain a valid symmetric encryption key and a correctly formed sphinx header")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: SerdeError,
|
||||
{
|
||||
ReplySurb::from_bytes(bytes)
|
||||
.map_err(|_| SerdeError::invalid_length(bytes.len(), &self))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(ReplySurbVisitor)
|
||||
}
|
||||
// pub(crate) used_key_rotation: SphinxKeyRotation,
|
||||
}
|
||||
|
||||
impl ReplySurb {
|
||||
@@ -123,6 +86,7 @@ impl ReplySurb {
|
||||
Ok(ReplySurb {
|
||||
surb: surb_material.construct_SURB().unwrap(),
|
||||
encryption_key: SurbEncryptionKey::new(rng),
|
||||
// used_key_rotation: SphinxKeyRotation::from(topology.current_key_rotation()),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,8 +162,14 @@ impl ReplySurb {
|
||||
.use_surb(message_bytes, packet_size.payload_size())
|
||||
.expect("this error indicates inconsistent message length checking - it shouldn't have happened!");
|
||||
|
||||
let first_hop_address = NymNodeRoutingAddress::try_from(first_hop).unwrap();
|
||||
let first_hop_address = NymNodeRoutingAddress::try_from(first_hop)?;
|
||||
|
||||
Ok((NymPacket::Sphinx(packet), first_hop_address))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AppliedReplySurb {
|
||||
packet: NymPacket,
|
||||
first_hop_address: NymNodeRoutingAddress,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ where
|
||||
)?,
|
||||
};
|
||||
|
||||
Ok(MixPacket::new(first_hop_address, packet, packet_type))
|
||||
todo!()
|
||||
// Ok(MixPacket::new(first_hop_address, packet, packet_type))
|
||||
}
|
||||
|
||||
/// Helper function used to determine if given message represents a loop cover message.
|
||||
|
||||
@@ -2,24 +2,35 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx_params::{PacketSize, PacketType, SphinxKeyRotation};
|
||||
use nym_sphinx_types::{NymPacket, NymPacketError};
|
||||
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use nym_sphinx_params::key_rotation::InvalidSphinxKeyRotation;
|
||||
use nym_sphinx_params::packet_sizes::InvalidPacketSize;
|
||||
use nym_sphinx_params::packet_types::InvalidPacketType;
|
||||
use std::net::SocketAddr;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MixPacketFormattingError {
|
||||
#[error("too few bytes provided to recover from bytes")]
|
||||
TooFewBytesProvided,
|
||||
#[error("provided packet mode is invalid")]
|
||||
InvalidPacketType,
|
||||
#[error("received request had invalid size - received {0}")]
|
||||
InvalidPacketSize(usize),
|
||||
|
||||
#[error("provided packet mode is invalid: {0}")]
|
||||
InvalidPacketType(#[from] InvalidPacketType),
|
||||
|
||||
#[error("received request had an invalid packet size: {0}")]
|
||||
InvalidPacketSize(#[from] InvalidPacketSize),
|
||||
|
||||
#[error("provided key rotation is invalid: {0}")]
|
||||
InvalidKeyRotation(#[from] InvalidSphinxKeyRotation),
|
||||
|
||||
#[error("address field was incorrectly encoded")]
|
||||
InvalidAddress,
|
||||
|
||||
#[error("received sphinx packet was malformed")]
|
||||
MalformedSphinxPacket,
|
||||
|
||||
#[error("Packet: {0}")]
|
||||
Packet(#[from] NymPacketError),
|
||||
}
|
||||
@@ -30,20 +41,12 @@ impl From<NymNodeRoutingAddressError> for MixPacketFormattingError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MixPacket {
|
||||
next_hop: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Debug for MixPacket {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"MixPacket to {:?} with packet_type {:?}. Packet {:?}",
|
||||
self.next_hop, self.packet_type, self.packet
|
||||
)
|
||||
}
|
||||
key_rotation: SphinxKeyRotation,
|
||||
}
|
||||
|
||||
impl MixPacket {
|
||||
@@ -51,11 +54,13 @@ impl MixPacket {
|
||||
next_hop: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Self {
|
||||
MixPacket {
|
||||
next_hop,
|
||||
packet,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +68,10 @@ impl MixPacket {
|
||||
self.next_hop
|
||||
}
|
||||
|
||||
pub fn next_hop_address(&self) -> SocketAddr {
|
||||
self.next_hop.into()
|
||||
}
|
||||
|
||||
pub fn packet(&self) -> &NymPacket {
|
||||
&self.packet
|
||||
}
|
||||
@@ -71,45 +80,94 @@ impl MixPacket {
|
||||
self.packet
|
||||
}
|
||||
|
||||
pub fn key_rotation(&self) -> SphinxKeyRotation {
|
||||
self.key_rotation
|
||||
}
|
||||
|
||||
pub fn packet_type(&self) -> PacketType {
|
||||
self.packet_type
|
||||
}
|
||||
|
||||
// the message is formatted as follows:
|
||||
// packet_type || FIRST_HOP || packet
|
||||
pub fn try_from_bytes(b: &[u8]) -> Result<Self, MixPacketFormattingError> {
|
||||
let packet_type = match PacketType::try_from(b[0]) {
|
||||
Ok(mode) => mode,
|
||||
Err(_) => return Err(MixPacketFormattingError::InvalidPacketType),
|
||||
};
|
||||
pub fn try_from_v1_bytes(b: &[u8]) -> Result<Self, MixPacketFormattingError> {
|
||||
// we need at least 1 byte to read packet type and another one to read type of the encoded first hop address
|
||||
if b.len() < 2 {
|
||||
return Err(MixPacketFormattingError::TooFewBytesProvided);
|
||||
}
|
||||
|
||||
let packet_type = PacketType::try_from(b[0])?;
|
||||
|
||||
let next_hop = NymNodeRoutingAddress::try_from_bytes(&b[1..])?;
|
||||
let addr_offset = next_hop.bytes_min_len();
|
||||
|
||||
let packet_data = &b[addr_offset + 1..];
|
||||
let packet_size = packet_data.len();
|
||||
if PacketSize::get_type(packet_size).is_err() {
|
||||
Err(MixPacketFormattingError::InvalidPacketSize(packet_size))
|
||||
} else {
|
||||
let packet = match packet_type {
|
||||
PacketType::Outfox => NymPacket::outfox_from_bytes(packet_data)?,
|
||||
_ => NymPacket::sphinx_from_bytes(packet_data)?,
|
||||
};
|
||||
|
||||
Ok(MixPacket {
|
||||
next_hop,
|
||||
packet,
|
||||
packet_type,
|
||||
})
|
||||
}
|
||||
// make sure the received data length corresponds to a valid packet
|
||||
let _ = PacketSize::get_type(packet_size)?;
|
||||
|
||||
let packet = match packet_type {
|
||||
PacketType::Mix => NymPacket::sphinx_from_bytes(packet_data)?,
|
||||
PacketType::Outfox => NymPacket::outfox_from_bytes(packet_data)?,
|
||||
};
|
||||
|
||||
Ok(MixPacket {
|
||||
next_hop,
|
||||
packet,
|
||||
packet_type,
|
||||
key_rotation: SphinxKeyRotation::Unknown,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Result<Vec<u8>, MixPacketFormattingError> {
|
||||
pub fn into_v1_bytes(self) -> Result<Vec<u8>, MixPacketFormattingError> {
|
||||
Ok(std::iter::once(self.packet_type as u8)
|
||||
.chain(self.next_hop.as_bytes())
|
||||
.chain(self.packet.to_bytes()?)
|
||||
.collect())
|
||||
}
|
||||
|
||||
// the message is formatted as follows:
|
||||
// packet_type || KEY_ROTATION || FIRST_HOP || packet
|
||||
pub fn try_from_v2_bytes(b: &[u8]) -> Result<Self, MixPacketFormattingError> {
|
||||
// we need at least 1 byte to read packet type, 1 byte to read key rotation
|
||||
// and finally another one to read type of the encoded first hop address
|
||||
if b.len() < 3 {
|
||||
return Err(MixPacketFormattingError::TooFewBytesProvided);
|
||||
}
|
||||
|
||||
let packet_type = PacketType::try_from(b[0])?;
|
||||
let key_rotation = SphinxKeyRotation::try_from(b[1])?;
|
||||
|
||||
let next_hop = NymNodeRoutingAddress::try_from_bytes(&b[2..])?;
|
||||
let addr_offset = next_hop.bytes_min_len();
|
||||
|
||||
let packet_data = &b[addr_offset + 2..];
|
||||
let packet_size = packet_data.len();
|
||||
|
||||
// make sure the received data length corresponds to a valid packet
|
||||
let _ = PacketSize::get_type(packet_size)?;
|
||||
|
||||
let packet = match packet_type {
|
||||
PacketType::Mix => NymPacket::sphinx_from_bytes(packet_data)?,
|
||||
PacketType::Outfox => NymPacket::outfox_from_bytes(packet_data)?,
|
||||
};
|
||||
|
||||
Ok(MixPacket {
|
||||
next_hop,
|
||||
packet,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_v2_bytes(self) -> Result<Vec<u8>, MixPacketFormattingError> {
|
||||
Ok(std::iter::once(self.packet_type as u8)
|
||||
.chain(std::iter::once(self.key_rotation as u8))
|
||||
.chain(self.next_hop.as_bytes())
|
||||
.chain(self.packet.to_bytes()?)
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: test for serialization and errors!
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::codec::NymCodecError;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::key_rotation::SphinxKeyRotation;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::packet_version::{PacketVersion, CURRENT_PACKET_VERSION};
|
||||
@@ -18,6 +19,14 @@ pub struct FramedNymPacket {
|
||||
pub(crate) packet: NymPacket,
|
||||
}
|
||||
|
||||
impl From<MixPacket> for FramedNymPacket {
|
||||
fn from(packet: MixPacket) -> Self {
|
||||
let typ = packet.packet_type();
|
||||
let rot = packet.key_rotation();
|
||||
FramedNymPacket::new(packet.into_packet(), typ, rot)
|
||||
}
|
||||
}
|
||||
|
||||
impl FramedNymPacket {
|
||||
pub fn new(
|
||||
packet: NymPacket,
|
||||
@@ -58,6 +67,10 @@ impl FramedNymPacket {
|
||||
&self.packet
|
||||
}
|
||||
|
||||
pub fn key_rotation(&self) -> SphinxKeyRotation {
|
||||
self.header.key_rotation
|
||||
}
|
||||
|
||||
pub fn is_sphinx(&self) -> bool {
|
||||
self.packet.is_sphinx()
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::packet::FramedNymPacket;
|
||||
use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError};
|
||||
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx_params::{PacketSize, PacketType, SphinxKeyRotation};
|
||||
use nym_sphinx_types::header::shared_secret::ExpandedSharedSecret;
|
||||
use nym_sphinx_types::{
|
||||
Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, NymPacketError,
|
||||
@@ -153,6 +153,7 @@ impl PartiallyUnwrappedPacket {
|
||||
let packet_size = self.received_data.packet_size();
|
||||
let packet_type = self.received_data.packet_type();
|
||||
|
||||
let key_rotation = self.received_data.header.key_rotation;
|
||||
let packet = self.received_data.into_inner();
|
||||
|
||||
// currently partial unwrapping is only implemented for sphinx packets.
|
||||
@@ -167,7 +168,7 @@ impl PartiallyUnwrappedPacket {
|
||||
return Err(PacketProcessingError::PartialOutfoxProcessing);
|
||||
};
|
||||
let processed_packet = packet.process_with_expanded_secret(&expanded_shared_secret)?;
|
||||
wrap_processed_sphinx_packet(processed_packet, packet_size, packet_type)
|
||||
wrap_processed_sphinx_packet(processed_packet, packet_size, packet_type, key_rotation)
|
||||
}
|
||||
|
||||
pub fn replay_tag(&self) -> Option<&[u8; REPLAY_TAG_SIZE]> {
|
||||
@@ -192,13 +193,14 @@ pub fn process_framed_packet(
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
let packet_size = received.packet_size();
|
||||
let packet_type = received.packet_type();
|
||||
let key_rotation = received.key_rotation();
|
||||
|
||||
// unwrap the sphinx packet
|
||||
let processed_packet = perform_framed_unwrapping(received, sphinx_key)?;
|
||||
|
||||
// for forward packets, extract next hop and set delay (but do NOT delay here)
|
||||
// for final packets, extract SURBAck
|
||||
perform_final_processing(processed_packet, packet_size, packet_type)
|
||||
perform_final_processing(processed_packet, packet_size, packet_type, key_rotation)
|
||||
}
|
||||
|
||||
fn perform_framed_unwrapping(
|
||||
@@ -223,6 +225,7 @@ fn wrap_processed_sphinx_packet(
|
||||
packet: nym_sphinx_types::ProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
let processing_data = match packet.data {
|
||||
ProcessedPacketData::ForwardHop {
|
||||
@@ -234,6 +237,7 @@ fn wrap_processed_sphinx_packet(
|
||||
next_hop_address,
|
||||
delay,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
),
|
||||
// right now there's no use for the surb_id included in the header - probably it should get removed from the
|
||||
// sphinx all together?
|
||||
@@ -246,6 +250,7 @@ fn wrap_processed_sphinx_packet(
|
||||
payload.recover_plaintext()?,
|
||||
packet_size,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
),
|
||||
}?;
|
||||
|
||||
@@ -259,6 +264,7 @@ fn wrap_processed_outfox_packet(
|
||||
packet: OutfoxProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
let next_address = *packet.next_address();
|
||||
let packet = packet.into_packet();
|
||||
@@ -268,6 +274,7 @@ fn wrap_processed_outfox_packet(
|
||||
packet.recover_plaintext()?.to_vec(),
|
||||
packet_size,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
)?;
|
||||
Ok(MixProcessingResult {
|
||||
packet_version: MixPacketVersion::Outfox,
|
||||
@@ -278,6 +285,7 @@ fn wrap_processed_outfox_packet(
|
||||
NymNodeRoutingAddress::try_from_bytes(&next_address)?,
|
||||
NymPacket::Outfox(packet),
|
||||
PacketType::Outfox,
|
||||
SphinxKeyRotation::Unknown,
|
||||
);
|
||||
Ok(MixProcessingResult {
|
||||
packet_version: MixPacketVersion::Outfox,
|
||||
@@ -293,13 +301,14 @@ fn perform_final_processing(
|
||||
packet: NymProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
match packet {
|
||||
NymProcessedPacket::Sphinx(packet) => {
|
||||
wrap_processed_sphinx_packet(packet, packet_size, packet_type)
|
||||
wrap_processed_sphinx_packet(packet, packet_size, packet_type, key_rotation)
|
||||
}
|
||||
NymProcessedPacket::Outfox(packet) => {
|
||||
wrap_processed_outfox_packet(packet, packet_size, packet_type)
|
||||
wrap_processed_outfox_packet(packet, packet_size, packet_type, key_rotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,8 +318,10 @@ fn process_final_hop(
|
||||
payload: Vec<u8>,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<MixProcessingResultData, PacketProcessingError> {
|
||||
let (forward_ack, message) = split_into_ack_and_message(payload, packet_size, packet_type)?;
|
||||
let (forward_ack, message) =
|
||||
split_into_ack_and_message(payload, packet_size, packet_type, key_rotation)?;
|
||||
|
||||
Ok(MixProcessingResultData::FinalHop {
|
||||
final_hop_data: ProcessedFinalHop {
|
||||
@@ -325,6 +336,7 @@ fn split_into_ack_and_message(
|
||||
data: Vec<u8>,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<(Option<MixPacket>, Vec<u8>), PacketProcessingError> {
|
||||
match packet_size {
|
||||
PacketSize::AckPacket | PacketSize::OutfoxAckPacket => {
|
||||
@@ -346,7 +358,7 @@ fn split_into_ack_and_message(
|
||||
return Err(err.into());
|
||||
}
|
||||
};
|
||||
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_type);
|
||||
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_type, key_rotation);
|
||||
Ok((Some(forward_ack), message))
|
||||
}
|
||||
}
|
||||
@@ -374,10 +386,11 @@ fn process_forward_hop(
|
||||
forward_address: NodeAddressBytes,
|
||||
delay: SphinxDelay,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
) -> Result<MixProcessingResultData, PacketProcessingError> {
|
||||
let next_hop_address = NymNodeRoutingAddress::try_from(forward_address)?;
|
||||
|
||||
let packet = MixPacket::new(next_hop_address, packet, packet_type);
|
||||
let packet = MixPacket::new(next_hop_address, packet, packet_type, key_rotation);
|
||||
Ok(MixProcessingResultData::ForwardHop {
|
||||
packet,
|
||||
delay: Some(delay),
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{received} is not a valid packet mode tag")]
|
||||
#[error("{received} is not a valid packet type tag")]
|
||||
pub struct InvalidPacketType {
|
||||
received: u8,
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use nym_sphinx_anonymous_replies::reply_surb::ReplySurb;
|
||||
use nym_sphinx_chunking::fragment::{Fragment, FragmentIdentifier};
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm};
|
||||
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, SphinxKeyRotation};
|
||||
use nym_sphinx_types::{Delay, NymPacket};
|
||||
use nym_topology::{NymRouteProvider, NymTopologyError};
|
||||
use rand::{CryptoRng, Rng, SeedableRng};
|
||||
@@ -152,14 +152,16 @@ pub trait FragmentPreparer {
|
||||
.apply_surb(packet_payload, packet_size, packet_type)
|
||||
.unwrap();
|
||||
|
||||
Ok(PreparedFragment {
|
||||
// the round-trip delay is the sum of delays of all hops on the forward route as
|
||||
// well as the total delay of the ack packet.
|
||||
// we don't know the delays inside the reply surbs so we use best-effort estimation from our poisson distribution
|
||||
total_delay: expected_forward_delay + ack_delay,
|
||||
mix_packet: MixPacket::new(first_hop_address, sphinx_packet, packet_type),
|
||||
fragment_identifier,
|
||||
})
|
||||
todo!("somehow get key rotation information here")
|
||||
|
||||
// Ok(PreparedFragment {
|
||||
// // the round-trip delay is the sum of delays of all hops on the forward route as
|
||||
// // well as the total delay of the ack packet.
|
||||
// // we don't know the delays inside the reply surbs so we use best-effort estimation from our poisson distribution
|
||||
// total_delay: expected_forward_delay + ack_delay,
|
||||
// mix_packet: MixPacket::new(first_hop_address, sphinx_packet, packet_type, key_rotation),
|
||||
// fragment_identifier,
|
||||
// })
|
||||
}
|
||||
|
||||
/// Tries to convert this [`Fragment`] into a [`SphinxPacket`] that can be sent through the Nym mix-network,
|
||||
@@ -211,6 +213,9 @@ pub trait FragmentPreparer {
|
||||
let packet_size = PacketSize::get_type_from_plaintext(expected_plaintext, packet_type)
|
||||
.expect("the message has been incorrectly fragmented");
|
||||
|
||||
let rotation_id = topology.current_key_rotation();
|
||||
let sphinx_key_rotation = SphinxKeyRotation::from(rotation_id);
|
||||
|
||||
let fragment_identifier = fragment.fragment_identifier();
|
||||
|
||||
// create an ack
|
||||
@@ -279,7 +284,7 @@ pub trait FragmentPreparer {
|
||||
// well as the total delay of the ack packet.
|
||||
// note that the last hop of the packet is a gateway that does not do any delays
|
||||
total_delay: delays.iter().take(delays.len() - 1).sum::<Delay>() + ack_delay,
|
||||
mix_packet: MixPacket::new(first_hop_address, packet, packet_type),
|
||||
mix_packet: MixPacket::new(first_hop_address, packet, packet_type, sphinx_key_rotation),
|
||||
fragment_identifier,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -129,6 +129,11 @@ impl NymRouteProvider {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_key_rotation(&self) -> u32 {
|
||||
todo!()
|
||||
// self.topology.rewarded_set.epoch_id
|
||||
}
|
||||
|
||||
pub fn new_empty(ignore_egress_epoch_roles: bool) -> NymRouteProvider {
|
||||
let this: Self = NymTopology::default().into();
|
||||
this.with_ignore_egress_epoch_roles(ignore_egress_epoch_roles)
|
||||
|
||||
@@ -16,7 +16,6 @@ use nym_node_requests::api::v1::mixnode::models::Mixnode;
|
||||
use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy;
|
||||
use nym_node_requests::api::v1::network_requester::models::NetworkRequester;
|
||||
use nym_node_requests::api::v1::node::models::{AuxiliaryDetails, HostSystem, NodeDescription};
|
||||
use nym_node_requests::api::SignedHostInformation;
|
||||
use nym_node_requests::routes;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -28,33 +28,33 @@ impl ActiveSphinxKeys {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn even(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
|
||||
pub(crate) fn even(&self) -> Option<SphinxKeyGuard> {
|
||||
let primary = self.inner.primary_key.load();
|
||||
if primary.is_even_rotation() {
|
||||
return Some(primary);
|
||||
return Some(SphinxKeyGuard::Primary(primary));
|
||||
}
|
||||
self.secondary()
|
||||
}
|
||||
|
||||
pub(crate) fn odd(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
|
||||
pub(crate) fn odd(&self) -> Option<SphinxKeyGuard> {
|
||||
let primary = self.inner.primary_key.load();
|
||||
if !primary.is_even_rotation() {
|
||||
return Some(primary);
|
||||
return Some(SphinxKeyGuard::Primary(primary));
|
||||
}
|
||||
self.secondary()
|
||||
}
|
||||
|
||||
pub(crate) fn primary(&self) -> impl Deref<Target = SphinxPrivateKey> {
|
||||
self.inner.primary_key.map(|k: &SphinxPrivateKey| k).load()
|
||||
pub(crate) fn primary(&self) -> SphinxKeyGuard {
|
||||
SphinxKeyGuard::Primary(self.inner.primary_key.load())
|
||||
}
|
||||
|
||||
pub(crate) fn secondary(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
|
||||
pub(crate) fn secondary(&self) -> Option<SphinxKeyGuard> {
|
||||
let guard = self.inner.secondary_key.load();
|
||||
if guard.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(SecondaryKeyGuard { guard })
|
||||
Some(SphinxKeyGuard::Secondary(SecondaryKeyGuard { guard }))
|
||||
}
|
||||
|
||||
// 1. generate new key
|
||||
@@ -87,6 +87,23 @@ impl ActiveSphinxKeys {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum SphinxKeyGuard {
|
||||
// Primary(Guard<Arc<SphinxPrivateKey>>),
|
||||
Primary(Guard<Arc<SphinxPrivateKey>>),
|
||||
Secondary(SecondaryKeyGuard),
|
||||
}
|
||||
|
||||
impl Deref for SphinxKeyGuard {
|
||||
type Target = SphinxPrivateKey;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
SphinxKeyGuard::Primary(g) => g.deref(),
|
||||
SphinxKeyGuard::Secondary(g) => g.deref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct SecondaryKeyGuard {
|
||||
guard: Guard<Option<Arc<SphinxPrivateKey>>>,
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ impl SphinxPrivateKey {
|
||||
self.inner.public_key()
|
||||
}
|
||||
|
||||
pub(crate) fn inner(&self) -> &x25519::PrivateKey {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub(crate) fn is_even_rotation(&self) -> bool {
|
||||
self.rotation_id & 1 == 0
|
||||
}
|
||||
|
||||
@@ -223,11 +223,15 @@ impl ConnectionHandler {
|
||||
SphinxKeyRotation::Unknown => {
|
||||
// we have to try both keys, start with the primary as it has higher likelihood of being correct
|
||||
// if let Ok(partially_unwrapped) = PartiallyUnwrappedPacket::new()
|
||||
match PartiallyUnwrappedPacket::new(packet, self.shared.sphinx_keys.primary()) {
|
||||
match PartiallyUnwrappedPacket::new(
|
||||
packet,
|
||||
self.shared.sphinx_keys.primary().inner().as_ref(),
|
||||
) {
|
||||
Ok(unwrapped_packet) => Ok(unwrapped_packet),
|
||||
Err((packet, err)) => {
|
||||
if let Some(secondary) = self.shared.sphinx_keys.secondary() {
|
||||
PartiallyUnwrappedPacket::new(packet, secondary).map_err(|(_, err)| err)
|
||||
PartiallyUnwrappedPacket::new(packet, secondary.inner().as_ref())
|
||||
.map_err(|(_, err)| err)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
@@ -238,13 +242,15 @@ impl ConnectionHandler {
|
||||
let Some(odd_key) = self.shared.sphinx_keys.odd() else {
|
||||
return Err(PacketProcessingError::ExpiredKey);
|
||||
};
|
||||
PartiallyUnwrappedPacket::new(packet, odd_key).map_err(|(_, err)| err)
|
||||
PartiallyUnwrappedPacket::new(packet, odd_key.inner().as_ref())
|
||||
.map_err(|(_, err)| err)
|
||||
}
|
||||
SphinxKeyRotation::EvenRotation => {
|
||||
let Some(even_key) = self.shared.sphinx_keys.even() else {
|
||||
return Err(PacketProcessingError::ExpiredKey);
|
||||
};
|
||||
PartiallyUnwrappedPacket::new(packet, even_key).map_err(|(_, err)| err)
|
||||
PartiallyUnwrappedPacket::new(packet, even_key.inner().as_ref())
|
||||
.map_err(|(_, err)| err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,19 +391,19 @@ impl ConnectionHandler {
|
||||
// and by the time we need it, the rotation info should be present)
|
||||
match packet.header().key_rotation {
|
||||
SphinxKeyRotation::Unknown => {
|
||||
process_framed_packet(packet, self.shared.sphinx_keys.primary())
|
||||
process_framed_packet(packet, self.shared.sphinx_keys.primary().inner().as_ref())
|
||||
}
|
||||
SphinxKeyRotation::OddRotation => {
|
||||
let Some(odd_key) = self.shared.sphinx_keys.odd() else {
|
||||
return Err(PacketProcessingError::ExpiredKey);
|
||||
};
|
||||
process_framed_packet(packet, odd_key)
|
||||
process_framed_packet(packet, odd_key.inner().as_ref())
|
||||
}
|
||||
SphinxKeyRotation::EvenRotation => {
|
||||
let Some(even_key) = self.shared.sphinx_keys.even() else {
|
||||
return Err(PacketProcessingError::ExpiredKey);
|
||||
};
|
||||
process_framed_packet(packet, even_key)
|
||||
process_framed_packet(packet, even_key.inner().as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,32 +58,20 @@ impl<C, F> PacketForwarder<C, F> {
|
||||
C: SendWithoutResponse,
|
||||
F: RoutingFilter,
|
||||
{
|
||||
let next_hop = packet.next_hop();
|
||||
let next_hop = packet.next_hop_address();
|
||||
|
||||
let packet_type = packet.packet_type();
|
||||
let packet = packet.into_packet();
|
||||
|
||||
if let Err(err) = self
|
||||
.mixnet_client
|
||||
.send_without_response(next_hop, packet, packet_type)
|
||||
{
|
||||
if let Err(err) = self.mixnet_client.send_without_response(packet) {
|
||||
if err.kind() == io::ErrorKind::WouldBlock {
|
||||
// we only know for sure if we dropped a packet if our sending queue was full
|
||||
// in any other case the connection might still be re-established (or created for the first time)
|
||||
// and the packet might get sent, but we won't know about it
|
||||
self.metrics
|
||||
.mixnet
|
||||
.egress_dropped_forward_packet(next_hop.into())
|
||||
self.metrics.mixnet.egress_dropped_forward_packet(next_hop)
|
||||
} else if err.kind() == io::ErrorKind::NotConnected {
|
||||
// let's give the benefit of the doubt and assume we manage to establish connection
|
||||
self.metrics
|
||||
.mixnet
|
||||
.egress_sent_forward_packet(next_hop.into())
|
||||
self.metrics.mixnet.egress_sent_forward_packet(next_hop)
|
||||
}
|
||||
} else {
|
||||
self.metrics
|
||||
.mixnet
|
||||
.egress_sent_forward_packet(next_hop.into())
|
||||
self.metrics.mixnet.egress_sent_forward_packet(next_hop)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +256,8 @@ impl ThroughputTestingClient {
|
||||
packet_bytes.append(&mut payload_bytes);
|
||||
|
||||
let forward_packet = NymPacket::sphinx_from_bytes(&packet_bytes)?;
|
||||
Ok(FramedNymPacket::new(forward_packet, Default::default()))
|
||||
todo!()
|
||||
// Ok(FramedNymPacket::new(forward_packet, Default::default()))
|
||||
}
|
||||
|
||||
async fn send_packets(&mut self) -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user