Outfox rest compat (#3333)
* Outfox forwarding compat * Tidy up interface * PacketSize compat
This commit is contained in:
Generated
+1
@@ -4336,6 +4336,7 @@ dependencies = [
|
||||
"nym-sphinx-addressing",
|
||||
"nym-sphinx-params",
|
||||
"nym-sphinx-types",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -136,7 +136,7 @@ impl From<PreparedFragment> for RealMessage {
|
||||
|
||||
impl RealMessage {
|
||||
pub(crate) fn packet_size(&self) -> usize {
|
||||
self.mix_packet.sphinx_packet().len()
|
||||
self.mix_packet.packet().len()
|
||||
}
|
||||
|
||||
pub(crate) fn new(mix_packet: MixPacket, fragment_id: Option<FragmentIdentifier>) -> Self {
|
||||
|
||||
@@ -571,7 +571,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
fn estimate_required_bandwidth(&self, packets: &[MixPacket]) -> i64 {
|
||||
packets
|
||||
.iter()
|
||||
.map(|packet| packet.sphinx_packet().len())
|
||||
.map(|packet| packet.packet().len())
|
||||
.sum::<usize>() as i64
|
||||
}
|
||||
|
||||
@@ -652,9 +652,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
if !self.authenticated {
|
||||
return Err(GatewayClientError::NotAuthenticated);
|
||||
}
|
||||
if (mix_packet.sphinx_packet().len() as i64) > self.bandwidth_remaining {
|
||||
if (mix_packet.packet().len() as i64) > self.bandwidth_remaining {
|
||||
return Err(GatewayClientError::NotEnoughBandwidth(
|
||||
mix_packet.sphinx_packet().len() as i64,
|
||||
mix_packet.packet().len() as i64,
|
||||
self.bandwidth_remaining,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use log::*;
|
||||
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx::framing::codec::NymCodec;
|
||||
use nym_sphinx::framing::packet::FramedNymPacket;
|
||||
use nym_sphinx::params::PacketMode;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_sphinx::NymPacket;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
@@ -52,7 +52,7 @@ pub trait SendWithoutResponse {
|
||||
&mut self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> io::Result<()>;
|
||||
}
|
||||
|
||||
@@ -198,11 +198,11 @@ impl SendWithoutResponse for Client {
|
||||
&mut self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> io::Result<()> {
|
||||
trace!("Sending packet to {:?}", address);
|
||||
let framed_packet =
|
||||
FramedNymPacket::new(packet, packet_mode, self.config.use_legacy_version);
|
||||
FramedNymPacket::new(packet, packet_type, self.config.use_legacy_version);
|
||||
|
||||
if let Some(sender) = self.conn_new.get_mut(&address) {
|
||||
if let Err(err) = sender.channel.try_send(framed_packet) {
|
||||
|
||||
@@ -6,7 +6,6 @@ use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::NymPacket;
|
||||
use std::time::Duration;
|
||||
|
||||
pub type MixForwardingSender = mpsc::UnboundedSender<MixPacket>;
|
||||
@@ -60,14 +59,14 @@ impl PacketForwarder {
|
||||
trace!("Going to forward packet to {:?}", mix_packet.next_hop());
|
||||
|
||||
let next_hop = mix_packet.next_hop();
|
||||
let packet_mode = mix_packet.packet_mode();
|
||||
let sphinx_packet = mix_packet.into_sphinx_packet();
|
||||
let packet_type = mix_packet.packet_type();
|
||||
let packet = mix_packet.into_packet();
|
||||
// we don't care about responses, we just want to fire packets
|
||||
// as quickly as possible
|
||||
|
||||
if let Err(err) =
|
||||
self.mixnet_client
|
||||
.send_without_response(next_hop, NymPacket::Sphinx(sphinx_packet), packet_mode)
|
||||
.send_without_response(next_hop, packet, packet_type)
|
||||
{
|
||||
debug!("failed to forward the packet - {err}")
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ use nym_sphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_framing::packet::FramedNymPacket;
|
||||
use nym_sphinx_params::{PacketMode, PacketSize};
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx_types::{
|
||||
Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, Payload,
|
||||
PrivateKey, ProcessedPacket, SphinxPacket,
|
||||
PrivateKey, ProcessedPacket,
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::Arc;
|
||||
@@ -53,7 +53,7 @@ impl SphinxPacketProcessor {
|
||||
feature = "cpucycles",
|
||||
instrument(skip(self, packet), fields(cpucycles))
|
||||
)]
|
||||
fn perform_initial_sphinx_packet_processing(
|
||||
fn perform_initial_packet_processing(
|
||||
&self,
|
||||
packet: NymPacket,
|
||||
) -> Result<ProcessedPacket, MixProcessingError> {
|
||||
@@ -75,14 +75,9 @@ impl SphinxPacketProcessor {
|
||||
received: FramedNymPacket,
|
||||
) -> Result<ProcessedPacket, MixProcessingError> {
|
||||
measure!({
|
||||
let packet_mode = received.packet_mode();
|
||||
let packet = received.into_inner();
|
||||
|
||||
if packet_mode.is_old_vpn() {
|
||||
return Err(MixProcessingError::ReceivedOldTypeVpnPacket);
|
||||
}
|
||||
|
||||
self.perform_initial_sphinx_packet_processing(packet)
|
||||
self.perform_initial_packet_processing(packet)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -90,14 +85,14 @@ impl SphinxPacketProcessor {
|
||||
/// and packs all the data in a way that can be easily sent to the next hop.
|
||||
fn process_forward_hop(
|
||||
&self,
|
||||
packet: SphinxPacket,
|
||||
packet: NymPacket,
|
||||
forward_address: NodeAddressBytes,
|
||||
delay: SphinxDelay,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> Result<MixProcessingResult, MixProcessingError> {
|
||||
let next_hop_address = NymNodeRoutingAddress::try_from(forward_address)?;
|
||||
|
||||
let mix_packet = MixPacket::new(next_hop_address, packet, packet_mode);
|
||||
let mix_packet = MixPacket::new(next_hop_address, packet, packet_type);
|
||||
Ok(MixProcessingResult::ForwardHop(mix_packet, Some(delay)))
|
||||
}
|
||||
|
||||
@@ -124,7 +119,7 @@ impl SphinxPacketProcessor {
|
||||
&self,
|
||||
data: Vec<u8>,
|
||||
packet_size: PacketSize,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> Result<(Option<MixPacket>, Vec<u8>), MixProcessingError> {
|
||||
match packet_size {
|
||||
PacketSize::AckPacket | PacketSize::OutfoxAckPacket => {
|
||||
@@ -142,7 +137,7 @@ impl SphinxPacketProcessor {
|
||||
trace!("received a normal packet!");
|
||||
let (ack_data, message) = self.split_hop_data_into_ack_and_message(data)?;
|
||||
let (ack_first_hop, ack_packet) = SurbAck::try_recover_first_hop_packet(&ack_data)?;
|
||||
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_mode);
|
||||
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_type);
|
||||
Ok((Some(forward_ack), message))
|
||||
}
|
||||
}
|
||||
@@ -156,12 +151,12 @@ impl SphinxPacketProcessor {
|
||||
destination: DestinationAddressBytes,
|
||||
payload: Payload,
|
||||
packet_size: PacketSize,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> Result<MixProcessingResult, MixProcessingError> {
|
||||
let packet_message = payload.recover_plaintext()?;
|
||||
|
||||
let (forward_ack, message) =
|
||||
self.split_into_ack_and_message(packet_message, packet_size, packet_mode)?;
|
||||
self.split_into_ack_and_message(packet_message, packet_size, packet_type)?;
|
||||
|
||||
Ok(MixProcessingResult::FinalHop(ProcessedFinalHop {
|
||||
destination,
|
||||
@@ -176,16 +171,16 @@ impl SphinxPacketProcessor {
|
||||
&self,
|
||||
packet: ProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> Result<MixProcessingResult, MixProcessingError> {
|
||||
match packet {
|
||||
ProcessedPacket::ForwardHop(packet, address, delay) => {
|
||||
self.process_forward_hop(*packet, address, delay, packet_mode)
|
||||
self.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?
|
||||
ProcessedPacket::FinalHop(destination, _, payload) => {
|
||||
self.process_final_hop(destination, payload, packet_size, packet_mode)
|
||||
self.process_final_hop(destination, payload, packet_size, packet_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,14 +196,14 @@ impl SphinxPacketProcessor {
|
||||
// explicit packet size will help to correctly parse final hop
|
||||
measure!({
|
||||
let packet_size = received.packet_size();
|
||||
let packet_mode = received.packet_mode();
|
||||
let packet_type = received.packet_type();
|
||||
|
||||
// unwrap the sphinx packet and if possible and appropriate, cache keys
|
||||
let processed_packet = self.perform_initial_unwrapping(received)?;
|
||||
|
||||
// for forward packets, extract next hop and set delay (but do NOT delay here)
|
||||
// for final packets, extract SURBAck
|
||||
self.perform_final_processing(processed_packet, packet_size, packet_mode)
|
||||
self.perform_final_processing(processed_packet, packet_size, packet_type)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,8 @@ use nym_sphinx_addressing::nodes::{
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::DEFAULT_NUM_MIX_HOPS;
|
||||
use nym_sphinx_types::builder::SphinxPacketBuilder;
|
||||
use nym_sphinx_types::SphinxError;
|
||||
use nym_sphinx_types::{
|
||||
delays::{self, Delay},
|
||||
SphinxPacket,
|
||||
};
|
||||
use nym_sphinx_types::delays::{self, Delay};
|
||||
use nym_sphinx_types::{NymPacket, NymPacketError};
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use std::convert::TryFrom;
|
||||
@@ -22,7 +19,7 @@ use std::time;
|
||||
use thiserror::Error;
|
||||
|
||||
pub struct SurbAck {
|
||||
surb_ack_packet: SphinxPacket,
|
||||
surb_ack_packet: NymPacket,
|
||||
first_hop_address: NymNodeRoutingAddress,
|
||||
expected_total_delay: Delay,
|
||||
}
|
||||
@@ -35,8 +32,8 @@ pub enum SurbAckRecoveryError {
|
||||
#[error("could not extract first hop address information - {0}")]
|
||||
InvalidAddress(#[from] NymNodeRoutingAddressError),
|
||||
|
||||
#[error("the contained sphinx packet was not correctly formed - {0}")]
|
||||
InvalidSphinxPacket(#[from] SphinxError),
|
||||
#[error("packet: {0}")]
|
||||
NymPacket(#[from] NymPacketError),
|
||||
}
|
||||
|
||||
impl SurbAck {
|
||||
@@ -58,10 +55,12 @@ impl SurbAck {
|
||||
|
||||
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
|
||||
|
||||
let surb_ack_packet = SphinxPacketBuilder::new()
|
||||
.with_payload_size(PacketSize::AckPacket.payload_size())
|
||||
.build_packet(surb_ack_payload, &route, &destination, &delays)
|
||||
.unwrap();
|
||||
let surb_ack_packet = NymPacket::Sphinx(
|
||||
SphinxPacketBuilder::new()
|
||||
.with_payload_size(PacketSize::AckPacket.payload_size())
|
||||
.build_packet(surb_ack_payload, &route, &destination, &delays)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
// in our case, the last hop is a gateway that does NOT do any delays
|
||||
let expected_total_delay = delays.iter().take(delays.len() - 1).sum();
|
||||
@@ -85,21 +84,21 @@ impl SurbAck {
|
||||
self.expected_total_delay
|
||||
}
|
||||
|
||||
pub fn prepare_for_sending(self) -> (Delay, Vec<u8>) {
|
||||
pub fn prepare_for_sending(self) -> Result<(Delay, Vec<u8>), SurbAckRecoveryError> {
|
||||
// SURB_FIRST_HOP || SURB_ACK
|
||||
let surb_bytes: Vec<_> = self
|
||||
.first_hop_address
|
||||
.as_zero_padded_bytes(MAX_NODE_ADDRESS_UNPADDED_LEN)
|
||||
.into_iter()
|
||||
.chain(self.surb_ack_packet.to_bytes().into_iter())
|
||||
.chain(self.surb_ack_packet.to_bytes()?.into_iter())
|
||||
.collect();
|
||||
(self.expected_total_delay, surb_bytes)
|
||||
Ok((self.expected_total_delay, surb_bytes))
|
||||
}
|
||||
|
||||
// partial reciprocal of `prepare_for_sending` performed by the gateway
|
||||
pub fn try_recover_first_hop_packet(
|
||||
b: &[u8],
|
||||
) -> Result<(NymNodeRoutingAddress, SphinxPacket), SurbAckRecoveryError> {
|
||||
) -> Result<(NymNodeRoutingAddress, NymPacket), SurbAckRecoveryError> {
|
||||
if b.len() != Self::len() {
|
||||
Err(SurbAckRecoveryError::InvalidPacketSize {
|
||||
received: b.len(),
|
||||
@@ -111,7 +110,7 @@ impl SurbAck {
|
||||
// TODO: this will be variable once/if we decide to introduce optimization described
|
||||
// in common/nymsphinx/chunking/src/lib.rs:available_plaintext_size()
|
||||
let address_offset = MAX_NODE_ADDRESS_UNPADDED_LEN;
|
||||
let packet = SphinxPacket::from_bytes(&b[address_offset..])?;
|
||||
let packet = NymPacket::sphinx_from_bytes(&b[address_offset..])?;
|
||||
|
||||
Ok((address, packet))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ 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::{ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
use nym_sphinx_types::{delays, SURBMaterial, SphinxError, SphinxPacket, SURB};
|
||||
use nym_sphinx_types::{delays, NymPacket, SURBMaterial, SphinxError, SURB};
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use serde::de::{Error as SerdeError, Visitor};
|
||||
@@ -173,7 +173,7 @@ impl ReplySurb {
|
||||
self,
|
||||
message: M,
|
||||
packet_size: PacketSize,
|
||||
) -> Result<(SphinxPacket, NymNodeRoutingAddress), ReplySurbError> {
|
||||
) -> Result<(NymPacket, NymNodeRoutingAddress), ReplySurbError> {
|
||||
let message_bytes = message.as_ref();
|
||||
if message_bytes.len() != packet_size.plaintext_size() {
|
||||
return Err(ReplySurbError::UnpaddedMessageError);
|
||||
@@ -187,6 +187,6 @@ impl ReplySurb {
|
||||
|
||||
let first_hop_address = NymNodeRoutingAddress::try_from(first_hop).unwrap();
|
||||
|
||||
Ok((packet, first_hop_address))
|
||||
Ok((NymPacket::Sphinx(packet), first_hop_address))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use nym_crypto::shared_key::new_ephemeral_shared_key;
|
||||
use nym_crypto::symmetric::stream_cipher;
|
||||
use nym_sphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError};
|
||||
use nym_sphinx_acknowledgements::AckKey;
|
||||
use nym_sphinx_addressing::clients::Recipient;
|
||||
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
@@ -11,10 +11,10 @@ use nym_sphinx_chunking::fragment::COVER_FRAG_ID;
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::{
|
||||
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, DEFAULT_NUM_MIX_HOPS,
|
||||
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketType, DEFAULT_NUM_MIX_HOPS,
|
||||
};
|
||||
use nym_sphinx_types::builder::SphinxPacketBuilder;
|
||||
use nym_sphinx_types::{delays, SphinxError};
|
||||
use nym_sphinx_types::{delays, NymPacket};
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use std::convert::TryFrom;
|
||||
@@ -28,8 +28,8 @@ pub enum CoverMessageError {
|
||||
#[error("Could not construct cover message due to invalid topology - {0}")]
|
||||
InvalidTopologyError(#[from] NymTopologyError),
|
||||
|
||||
#[error("Could not construct a valid sphinx packet - {0}")]
|
||||
SphinxError(#[from] SphinxError),
|
||||
#[error("SurbAck: {0}")]
|
||||
SurbAck(#[from] SurbAckRecoveryError),
|
||||
}
|
||||
|
||||
pub fn generate_loop_cover_surb_ack<R>(
|
||||
@@ -67,7 +67,7 @@ where
|
||||
// we don't care about total ack delay - we will not be retransmitting it anyway
|
||||
let (_, ack_bytes) =
|
||||
generate_loop_cover_surb_ack(rng, topology, ack_key, full_address, average_ack_delay)?
|
||||
.prepare_for_sending();
|
||||
.prepare_for_sending()?;
|
||||
|
||||
// cover message can't be distinguishable from a normal traffic so we have to go through
|
||||
// all the effort of key generation, encryption, etc. Note here we are generating shared key
|
||||
@@ -111,15 +111,17 @@ where
|
||||
let destination = full_address.as_sphinx_destination();
|
||||
|
||||
// once merged, that's an easy rng injection point for sphinx packets : )
|
||||
let packet = SphinxPacketBuilder::new()
|
||||
.with_payload_size(packet_size.payload_size())
|
||||
.build_packet(packet_payload, &route, &destination, &delays)
|
||||
.unwrap();
|
||||
let packet = NymPacket::Sphinx(
|
||||
SphinxPacketBuilder::new()
|
||||
.with_payload_size(packet_size.payload_size())
|
||||
.build_packet(packet_payload, &route, &destination, &delays)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let first_hop_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
|
||||
|
||||
Ok(MixPacket::new(first_hop_address, packet, PacketMode::Mix))
|
||||
Ok(MixPacket::new(first_hop_address, packet, PacketType::Mix))
|
||||
}
|
||||
|
||||
/// Helper function used to determine if given message represents a loop cover message.
|
||||
|
||||
@@ -12,3 +12,4 @@ nym-sphinx-addressing = { path = "../addressing" }
|
||||
nym-sphinx-params = { path = "../params" }
|
||||
nym-sphinx-types = { path = "../types" }
|
||||
nym-outfox = { path = "../../../nym-outfox" }
|
||||
thiserror = "1"
|
||||
|
||||
@@ -2,42 +2,28 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use nym_sphinx_params::{PacketMode, PacketSize};
|
||||
use nym_sphinx_types::SphinxPacket;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx_types::{NymPacket, NymPacketError};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MixPacketFormattingError {
|
||||
#[error("too few bytes provided to recover from bytes")]
|
||||
TooFewBytesProvided,
|
||||
InvalidPacketMode,
|
||||
#[error("provided packet mode is invalid")]
|
||||
InvalidPacketType,
|
||||
#[error("received request had invalid size - received {0}")]
|
||||
InvalidPacketSize(usize),
|
||||
#[error("address field was incorrectly encoded")]
|
||||
InvalidAddress,
|
||||
#[error("received sphinx packet was malformed")]
|
||||
MalformedSphinxPacket,
|
||||
#[error("Packet: {0}")]
|
||||
Packet(#[from] NymPacketError),
|
||||
}
|
||||
|
||||
impl Display for MixPacketFormattingError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
use MixPacketFormattingError::*;
|
||||
match self {
|
||||
TooFewBytesProvided => write!(f, "Too few bytes provided to recover from bytes"),
|
||||
InvalidAddress => write!(f, "address field was incorrectly encoded"),
|
||||
InvalidPacketSize(actual) =>
|
||||
write!(
|
||||
f,
|
||||
"received request had invalid size. (actual: {}, but expected one of: {} (ACK), {} (REGULAR), {}, {}, {} (EXTENDED))",
|
||||
actual, PacketSize::AckPacket.size(), PacketSize::RegularPacket.size(),
|
||||
PacketSize::ExtendedPacket8.size(), PacketSize::ExtendedPacket16.size(),
|
||||
PacketSize::ExtendedPacket32.size()
|
||||
),
|
||||
MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"),
|
||||
InvalidPacketMode => write!(f, "provided packet mode is invalid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for MixPacketFormattingError {}
|
||||
|
||||
impl From<NymNodeRoutingAddressError> for MixPacketFormattingError {
|
||||
fn from(_: NymNodeRoutingAddressError) -> Self {
|
||||
MixPacketFormattingError::InvalidAddress
|
||||
@@ -46,19 +32,16 @@ impl From<NymNodeRoutingAddressError> for MixPacketFormattingError {
|
||||
|
||||
pub struct MixPacket {
|
||||
next_hop: NymNodeRoutingAddress,
|
||||
sphinx_packet: SphinxPacket,
|
||||
packet_mode: PacketMode,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Debug for MixPacket {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"MixPacket to {:?} with packet_mode {:?}. Sphinx header: {:?}, payload length: {}",
|
||||
self.next_hop,
|
||||
self.packet_mode,
|
||||
self.sphinx_packet.header,
|
||||
self.sphinx_packet.payload.len()
|
||||
"MixPacket to {:?} with packet_type {:?}. Packet {:?}",
|
||||
self.next_hop, self.packet_type, self.packet
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -66,13 +49,13 @@ impl Debug for MixPacket {
|
||||
impl MixPacket {
|
||||
pub fn new(
|
||||
next_hop: NymNodeRoutingAddress,
|
||||
sphinx_packet: SphinxPacket,
|
||||
packet_mode: PacketMode,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
) -> Self {
|
||||
MixPacket {
|
||||
next_hop,
|
||||
sphinx_packet,
|
||||
packet_mode,
|
||||
packet,
|
||||
packet_type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,52 +63,52 @@ impl MixPacket {
|
||||
self.next_hop
|
||||
}
|
||||
|
||||
pub fn sphinx_packet(&self) -> &SphinxPacket {
|
||||
&self.sphinx_packet
|
||||
pub fn packet(&self) -> &NymPacket {
|
||||
&self.packet
|
||||
}
|
||||
|
||||
pub fn into_sphinx_packet(self) -> SphinxPacket {
|
||||
self.sphinx_packet
|
||||
pub fn into_packet(self) -> NymPacket {
|
||||
self.packet
|
||||
}
|
||||
|
||||
pub fn packet_mode(&self) -> PacketMode {
|
||||
self.packet_mode
|
||||
pub fn packet_type(&self) -> PacketType {
|
||||
self.packet_type
|
||||
}
|
||||
|
||||
// the message is formatted as follows:
|
||||
// PACKET_MODE || FIRST_HOP || SPHINX_PACKET
|
||||
// packet_type || FIRST_HOP || packet
|
||||
pub fn try_from_bytes(b: &[u8]) -> Result<Self, MixPacketFormattingError> {
|
||||
let packet_mode = match PacketMode::try_from(b[0]) {
|
||||
let packet_type = match PacketType::try_from(b[0]) {
|
||||
Ok(mode) => mode,
|
||||
Err(_) => return Err(MixPacketFormattingError::InvalidPacketMode),
|
||||
Err(_) => return Err(MixPacketFormattingError::InvalidPacketType),
|
||||
};
|
||||
|
||||
let next_hop = NymNodeRoutingAddress::try_from_bytes(&b[1..])?;
|
||||
let addr_offset = next_hop.bytes_min_len();
|
||||
|
||||
let sphinx_packet_data = &b[addr_offset + 1..];
|
||||
let packet_size = sphinx_packet_data.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 sphinx_packet = match SphinxPacket::from_bytes(sphinx_packet_data) {
|
||||
Ok(packet) => packet,
|
||||
Err(_) => return Err(MixPacketFormattingError::MalformedSphinxPacket),
|
||||
let packet = match packet_type {
|
||||
PacketType::Outfox => NymPacket::outfox_from_bytes(packet_data)?,
|
||||
_ => NymPacket::sphinx_from_bytes(packet_data)?,
|
||||
};
|
||||
|
||||
Ok(MixPacket {
|
||||
next_hop,
|
||||
sphinx_packet,
|
||||
packet_mode,
|
||||
packet,
|
||||
packet_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
std::iter::once(self.packet_mode as u8)
|
||||
pub fn into_bytes(self) -> Result<Vec<u8>, MixPacketFormattingError> {
|
||||
Ok(std::iter::once(self.packet_type as u8)
|
||||
.chain(self.next_hop.as_bytes().into_iter())
|
||||
.chain(self.sphinx_packet.to_bytes().into_iter())
|
||||
.collect()
|
||||
.chain(self.packet.to_bytes()?.into_iter())
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
use crate::packet::{FramedNymPacket, Header};
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use nym_sphinx_params::packet_modes::InvalidPacketMode;
|
||||
use nym_sphinx_params::packet_sizes::{InvalidPacketSize, PacketSize};
|
||||
use nym_sphinx_params::PacketMode;
|
||||
use nym_sphinx_types::{NymPacket, NymPacketError, SphinxError};
|
||||
use nym_sphinx_types::{OutfoxError, OutfoxPacket, SphinxPacket};
|
||||
use nym_sphinx_params::packet_types::InvalidPacketType;
|
||||
use nym_sphinx_params::PacketType;
|
||||
use nym_sphinx_types::{NymPacket, NymPacketError};
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
@@ -18,13 +17,7 @@ pub enum NymCodecError {
|
||||
InvalidPacketSize(#[from] InvalidPacketSize),
|
||||
|
||||
#[error("the packet mode information was malformed - {0}")]
|
||||
InvalidPacketMode(#[from] InvalidPacketMode),
|
||||
|
||||
#[error("the actual sphinx packet was malformed - {0}")]
|
||||
MalformedSphinxPacket(#[from] SphinxError),
|
||||
|
||||
#[error("the actual outfox packet was malformed - {0}")]
|
||||
MalformedOutfoxPacket(#[from] OutfoxError),
|
||||
InvalidPacketType(#[from] InvalidPacketType),
|
||||
|
||||
#[error("encountered an IO error - {0}")]
|
||||
IoError(#[from] io::Error),
|
||||
@@ -46,17 +39,6 @@ pub struct NymCodec;
|
||||
impl Encoder<FramedNymPacket> for NymCodec {
|
||||
type Error = NymCodecError;
|
||||
|
||||
// fn encode_serde(&mut self, item: FramedNymPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
// let encoded_size = bincode::serialized_size(&item).unwrap() as u32;
|
||||
// dst.put_u32(encoded_size);
|
||||
// dst.put(
|
||||
// bincode::serialize(&item)
|
||||
// .map_err(|_| NymCodecError::ToBytes)?
|
||||
// .as_slice(),
|
||||
// );
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
fn encode(&mut self, item: FramedNymPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
item.header.encode(dst);
|
||||
let packet_bytes = item.packet.to_bytes()?;
|
||||
@@ -69,39 +51,6 @@ impl Decoder for NymCodec {
|
||||
type Item = FramedNymPacket;
|
||||
type Error = NymCodecError;
|
||||
|
||||
// fn decode_serde(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
// if src.is_empty() {
|
||||
// // can't do anything if we have no bytes, but let's reserve enough for the most
|
||||
// // conservative case, i.e. receiving an ack packet
|
||||
// src.reserve(Header::LEGACY_SIZE + PacketSize::AckPacket.size());
|
||||
// return Ok(None);
|
||||
// }
|
||||
|
||||
// let next_size = if let Some(size) = src.get(..4) {
|
||||
// u32::from_be_bytes(size.try_into().unwrap()) as usize
|
||||
// } else {
|
||||
// 0
|
||||
// };
|
||||
|
||||
// if next_size == 0 {
|
||||
// return Ok(None);
|
||||
// }
|
||||
|
||||
// if let Some(next_packet) = src.get(4..next_size + 4) {
|
||||
// match bincode::deserialize::<Self::Item>(next_packet) {
|
||||
// Ok(packet) => {
|
||||
// src.advance(next_size + 4);
|
||||
// return Ok(Some(packet));
|
||||
// }
|
||||
// Err(_) => {
|
||||
// println!("Could not decode packet");
|
||||
// return Ok(None);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Ok(None)
|
||||
// }
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
if src.is_empty() {
|
||||
// can't do anything if we have no bytes, but let's reserve enough for the most
|
||||
@@ -132,9 +81,9 @@ impl Decoder for NymCodec {
|
||||
let packet = if let Some(slice) = packet_bytes.get(..) {
|
||||
// here it could be debatable whether stream is corrupt or not,
|
||||
// but let's go with the safer approach and assume it is.
|
||||
match header.packet_mode {
|
||||
PacketMode::Outfox => NymPacket::Outfox(OutfoxPacket::try_from(slice)?),
|
||||
_ => NymPacket::Sphinx(SphinxPacket::from_bytes(slice)?),
|
||||
match header.packet_type {
|
||||
PacketType::Outfox => NymPacket::outfox_from_bytes(slice)?,
|
||||
PacketType::Mix => NymPacket::sphinx_from_bytes(slice)?,
|
||||
}
|
||||
} else {
|
||||
return Ok(None);
|
||||
@@ -176,13 +125,12 @@ impl Decoder for NymCodec {
|
||||
#[cfg(test)]
|
||||
mod packet_encoding {
|
||||
use super::*;
|
||||
use nym_sphinx_types::builder::SphinxPacketBuilder;
|
||||
use nym_sphinx_types::{
|
||||
crypto, Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
|
||||
DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH, OUTFOX_PACKET_OVERHEAD,
|
||||
DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
};
|
||||
|
||||
fn make_valid_outfox_packet(size: PacketSize) -> OutfoxPacket {
|
||||
fn make_valid_outfox_packet(size: PacketSize) -> NymPacket {
|
||||
let (_, node1_pk) = crypto::keygen();
|
||||
let node1 = Node::new(
|
||||
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
|
||||
@@ -199,14 +147,14 @@ mod packet_encoding {
|
||||
node3_pk,
|
||||
);
|
||||
|
||||
let route = [node1, node2, node3];
|
||||
let route = &[node1, node2, node3];
|
||||
|
||||
let payload = vec![1; 48];
|
||||
|
||||
OutfoxPacket::build(&payload, &route, Some(size.size() - OUTFOX_PACKET_OVERHEAD)).unwrap()
|
||||
NymPacket::outfox_build(payload, route, Some(size.plaintext_size())).unwrap()
|
||||
}
|
||||
|
||||
fn make_valid_sphinx_packet(size: PacketSize) -> SphinxPacket {
|
||||
fn make_valid_sphinx_packet(size: PacketSize) -> NymPacket {
|
||||
let (_, node1_pk) = crypto::keygen();
|
||||
let node1 = Node::new(
|
||||
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
|
||||
@@ -233,9 +181,7 @@ mod packet_encoding {
|
||||
SphinxDelay::new_from_nanos(42),
|
||||
SphinxDelay::new_from_nanos(42),
|
||||
];
|
||||
SphinxPacketBuilder::new()
|
||||
.with_payload_size(size.payload_size())
|
||||
.build_packet(b"foomp", &route, &destination, &delays)
|
||||
NymPacket::sphinx_build(size.payload_size(), b"foomp", &route, &destination, &delays)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -243,11 +189,11 @@ mod packet_encoding {
|
||||
fn whole_packet_can_be_decoded_from_a_valid_encoded_instance() {
|
||||
let header = Default::default();
|
||||
let sphinx_packet = make_valid_sphinx_packet(Default::default());
|
||||
let sphinx_bytes = sphinx_packet.to_bytes();
|
||||
let sphinx_bytes = sphinx_packet.to_bytes().unwrap();
|
||||
|
||||
let packet = FramedNymPacket {
|
||||
header,
|
||||
packet: NymPacket::Sphinx(sphinx_packet),
|
||||
packet: sphinx_packet,
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
@@ -264,12 +210,9 @@ mod packet_encoding {
|
||||
let packet = make_valid_outfox_packet(PacketSize::OutfoxRegularPacket);
|
||||
let packet_bytes = packet.to_bytes().unwrap();
|
||||
|
||||
OutfoxPacket::try_from(packet_bytes.as_slice()).unwrap();
|
||||
NymPacket::outfox_from_bytes(packet_bytes.as_slice()).unwrap();
|
||||
|
||||
let packet = FramedNymPacket {
|
||||
header,
|
||||
packet: NymPacket::Outfox(packet),
|
||||
};
|
||||
let packet = FramedNymPacket { header, packet };
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
NymCodec.encode(packet, &mut bytes).unwrap();
|
||||
@@ -283,7 +226,7 @@ mod packet_encoding {
|
||||
mod decode_will_allocate_enough_bytes_for_next_call {
|
||||
use super::*;
|
||||
use nym_sphinx_params::packet_version::PacketVersion;
|
||||
use nym_sphinx_params::PacketMode;
|
||||
use nym_sphinx_params::PacketType;
|
||||
|
||||
#[test]
|
||||
fn for_empty_bytes() {
|
||||
@@ -355,7 +298,7 @@ mod packet_encoding {
|
||||
packet_version: PacketVersion::Legacy,
|
||||
..Default::default()
|
||||
},
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
@@ -372,7 +315,7 @@ mod packet_encoding {
|
||||
// if full frame is used exactly, there should be enough space for header + ack packet
|
||||
let packet = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
@@ -401,13 +344,13 @@ mod packet_encoding {
|
||||
packet_version: PacketVersion::Legacy,
|
||||
..Default::default()
|
||||
},
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
NymCodec.encode(first_packet, &mut bytes).unwrap();
|
||||
bytes.put_u8(packet_size as u8);
|
||||
bytes.put_u8(PacketMode::default() as u8);
|
||||
bytes.put_u8(PacketType::default() as u8);
|
||||
assert!(NymCodec.decode(&mut bytes).unwrap().is_some());
|
||||
|
||||
assert!(bytes.capacity() >= Header::LEGACY_SIZE + packet_size.size())
|
||||
@@ -428,14 +371,14 @@ mod packet_encoding {
|
||||
for packet_size in packet_sizes {
|
||||
let first_packet = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
NymCodec.encode(first_packet, &mut bytes).unwrap();
|
||||
bytes.put_u8(PacketVersion::new_versioned(123).as_u8().unwrap());
|
||||
bytes.put_u8(packet_size as u8);
|
||||
bytes.put_u8(PacketMode::default() as u8);
|
||||
bytes.put_u8(PacketType::default() as u8);
|
||||
assert!(NymCodec.decode(&mut bytes).unwrap().is_some());
|
||||
|
||||
// assert!(bytes.capacity() >= Header::VERSIONED_SIZE + packet_size.size())
|
||||
@@ -447,12 +390,12 @@ mod packet_encoding {
|
||||
fn can_decode_two_packets_immediately() {
|
||||
let packet1 = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let packet2 = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
@@ -469,12 +412,12 @@ mod packet_encoding {
|
||||
fn can_decode_two_packets_in_separate_calls() {
|
||||
let packet1 = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let packet2 = FramedNymPacket {
|
||||
header: Header::default(),
|
||||
packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())),
|
||||
packet: make_valid_sphinx_packet(Default::default()),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::new();
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::codec::NymCodecError;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::packet_version::PacketVersion;
|
||||
use nym_sphinx_params::PacketMode;
|
||||
use nym_sphinx_params::PacketType;
|
||||
use nym_sphinx_types::NymPacket;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
@@ -19,7 +19,7 @@ pub struct FramedNymPacket {
|
||||
}
|
||||
|
||||
impl FramedNymPacket {
|
||||
pub fn new(packet: NymPacket, packet_mode: PacketMode, use_legacy_version: bool) -> Self {
|
||||
pub fn new(packet: NymPacket, packet_type: PacketType, use_legacy_version: bool) -> Self {
|
||||
// If this fails somebody is using the library in a super incorrect way, because they
|
||||
// already managed to somehow create a sphinx packet
|
||||
let packet_size = PacketSize::get_type(packet.len()).unwrap();
|
||||
@@ -28,7 +28,7 @@ impl FramedNymPacket {
|
||||
header: Header {
|
||||
packet_version: PacketVersion::new(use_legacy_version),
|
||||
packet_size,
|
||||
packet_mode,
|
||||
packet_type,
|
||||
},
|
||||
packet,
|
||||
}
|
||||
@@ -42,8 +42,8 @@ impl FramedNymPacket {
|
||||
self.header.packet_size
|
||||
}
|
||||
|
||||
pub fn packet_mode(&self) -> PacketMode {
|
||||
self.header.packet_mode
|
||||
pub fn packet_type(&self) -> PacketType {
|
||||
self.header.packet_type
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> NymPacket {
|
||||
@@ -69,9 +69,9 @@ pub struct Header {
|
||||
///
|
||||
/// TODO: ask @AP whether this can be sent like this - could it introduce some anonymity issues?
|
||||
/// (note: this will be behind some encryption, either something implemented by us or some SSL action)
|
||||
// Note: currently packet_mode is deprecated but is still left as a concept behind to not break
|
||||
// Note: currently packet_type is deprecated but is still left as a concept behind to not break
|
||||
// compatibility with existing network
|
||||
pub(crate) packet_mode: PacketMode,
|
||||
pub(crate) packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
@@ -82,7 +82,7 @@ impl Header {
|
||||
Header {
|
||||
packet_version: PacketVersion::default(),
|
||||
packet_size: PacketSize::OutfoxRegularPacket,
|
||||
packet_mode: PacketMode::Outfox,
|
||||
packet_type: PacketType::Outfox,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ impl Header {
|
||||
}
|
||||
|
||||
dst.put_u8(self.packet_size as u8);
|
||||
dst.put_u8(self.packet_mode as u8);
|
||||
dst.put_u8(self.packet_type as u8);
|
||||
// reserve bytes for the actual packet
|
||||
dst.reserve(self.packet_size.size());
|
||||
}
|
||||
@@ -120,7 +120,7 @@ impl Header {
|
||||
Ok(Some(Header {
|
||||
packet_version,
|
||||
packet_size: PacketSize::try_from(src[0])?,
|
||||
packet_mode: PacketMode::try_from(src[1])?,
|
||||
packet_type: PacketType::try_from(src[1])?,
|
||||
}))
|
||||
} else if src.len() < Self::VERSIONED_SIZE {
|
||||
// we're missing that 1 byte to read the full header...
|
||||
@@ -130,7 +130,7 @@ impl Header {
|
||||
Ok(Some(Header {
|
||||
packet_version,
|
||||
packet_size: PacketSize::try_from(src[1])?,
|
||||
packet_mode: PacketMode::try_from(src[2])?,
|
||||
packet_type: PacketType::try_from(src[2])?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ mod header_encoding {
|
||||
[
|
||||
PacketVersion::new_versioned(123).as_u8().unwrap(),
|
||||
unknown_packet_size,
|
||||
PacketMode::default() as u8,
|
||||
PacketType::default() as u8,
|
||||
]
|
||||
.as_ref(),
|
||||
);
|
||||
@@ -169,12 +169,12 @@ mod header_encoding {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decoding_will_fail_for_unknown_packet_mode() {
|
||||
let unknown_packet_mode: u8 = 255;
|
||||
fn decoding_will_fail_for_unknown_packet_type() {
|
||||
let unknown_packet_type: u8 = 255;
|
||||
// make sure this is still 'unknown' for if we make changes in the future
|
||||
assert!(PacketMode::try_from(unknown_packet_mode).is_err());
|
||||
assert!(PacketType::try_from(unknown_packet_type).is_err());
|
||||
|
||||
let mut bytes = BytesMut::from([PacketSize::default() as u8, unknown_packet_mode].as_ref());
|
||||
let mut bytes = BytesMut::from([PacketSize::default() as u8, unknown_packet_type].as_ref());
|
||||
assert!(Header::decode(&mut bytes).is_err())
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ use nym_crypto::ctr;
|
||||
type Aes128Ctr = ctr::Ctr64BE<Aes128>;
|
||||
|
||||
// Re-export for ease of use
|
||||
pub use packet_modes::PacketMode;
|
||||
pub use packet_sizes::PacketSize;
|
||||
pub use packet_types::PacketType;
|
||||
|
||||
pub mod packet_modes;
|
||||
pub mod packet_sizes;
|
||||
pub mod packet_types;
|
||||
pub mod packet_version;
|
||||
|
||||
// If somebody can provide an argument why it might be reasonable to have more than 255 mix hops,
|
||||
@@ -29,7 +29,7 @@ pub type SerializedFragmentIdentifier = [u8; FRAG_ID_LEN];
|
||||
// when packet header gets serialized, the following bytes (in that order) are put onto the wire:
|
||||
// - packet_version (starting with v1.1.0)
|
||||
// - packet_size indicator
|
||||
// - packet_mode
|
||||
// - packet_type
|
||||
// it also just so happens that the only valid values for packet_size indicator include values 1-6
|
||||
// therefore if we receive byte `7` (or larger than that) we'll know we received a versioned packet,
|
||||
// otherwise we should treat it as legacy
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::FRAG_ID_LEN;
|
||||
use nym_sphinx_types::header::HEADER_SIZE;
|
||||
use nym_sphinx_types::{OUTFOX_PACKET_OVERHEAD, PAYLOAD_OVERHEAD_SIZE};
|
||||
use nym_sphinx_types::{MIX_PARAMS_LEN, OUTFOX_PACKET_OVERHEAD, PAYLOAD_OVERHEAD_SIZE};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
@@ -195,12 +195,42 @@ impl PacketSize {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn header_size(&self) -> usize {
|
||||
match self {
|
||||
PacketSize::RegularPacket
|
||||
| PacketSize::AckPacket
|
||||
| PacketSize::ExtendedPacket8
|
||||
| PacketSize::ExtendedPacket16
|
||||
| PacketSize::ExtendedPacket32 => HEADER_SIZE,
|
||||
PacketSize::OutfoxRegularPacket
|
||||
| PacketSize::OutfoxAckPacket
|
||||
| PacketSize::OutfoxExtendedPacket8
|
||||
| PacketSize::OutfoxExtendedPacket16
|
||||
| PacketSize::OutfoxExtendedPacket32 => MIX_PARAMS_LEN,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn payload_overhead(&self) -> usize {
|
||||
match self {
|
||||
PacketSize::RegularPacket
|
||||
| PacketSize::AckPacket
|
||||
| PacketSize::ExtendedPacket8
|
||||
| PacketSize::ExtendedPacket16
|
||||
| PacketSize::ExtendedPacket32 => PAYLOAD_OVERHEAD_SIZE,
|
||||
PacketSize::OutfoxRegularPacket
|
||||
| PacketSize::OutfoxAckPacket
|
||||
| PacketSize::OutfoxExtendedPacket8
|
||||
| PacketSize::OutfoxExtendedPacket16
|
||||
| PacketSize::OutfoxExtendedPacket32 => OUTFOX_PACKET_OVERHEAD - MIX_PARAMS_LEN,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn plaintext_size(self) -> usize {
|
||||
self.size() - HEADER_SIZE - PAYLOAD_OVERHEAD_SIZE
|
||||
self.size() - self.header_size() - self.payload_overhead()
|
||||
}
|
||||
|
||||
pub const fn payload_size(self) -> usize {
|
||||
self.size() - HEADER_SIZE
|
||||
self.size() - self.header_size()
|
||||
}
|
||||
|
||||
pub fn get_type(size: usize) -> Result<Self, InvalidPacketSize> {
|
||||
@@ -214,6 +244,16 @@ impl PacketSize {
|
||||
Ok(PacketSize::ExtendedPacket16)
|
||||
} else if PacketSize::ExtendedPacket32.size() == size {
|
||||
Ok(PacketSize::ExtendedPacket32)
|
||||
} else if PacketSize::OutfoxRegularPacket.size() == size {
|
||||
Ok(PacketSize::OutfoxRegularPacket)
|
||||
} else if PacketSize::OutfoxAckPacket.size() == size {
|
||||
Ok(PacketSize::OutfoxAckPacket)
|
||||
} else if PacketSize::OutfoxExtendedPacket8.size() == size {
|
||||
Ok(PacketSize::OutfoxExtendedPacket8)
|
||||
} else if PacketSize::OutfoxExtendedPacket16.size() == size {
|
||||
Ok(PacketSize::OutfoxExtendedPacket16)
|
||||
} else if PacketSize::OutfoxExtendedPacket32.size() == size {
|
||||
Ok(PacketSize::OutfoxExtendedPacket32)
|
||||
} else {
|
||||
Err(InvalidPacketSize::UnknownPacketSize { received: size })
|
||||
}
|
||||
@@ -243,8 +283,12 @@ impl PacketSize {
|
||||
}
|
||||
|
||||
pub fn get_type_from_plaintext(plaintext_size: usize) -> Result<Self, InvalidPacketSize> {
|
||||
let packet_size = plaintext_size + SPHINX_PACKET_OVERHEAD;
|
||||
Self::get_type(packet_size)
|
||||
let sphinx_packet_size = plaintext_size + SPHINX_PACKET_OVERHEAD;
|
||||
let outfox_packet_size = plaintext_size + OUTFOX_PACKET_OVERHEAD;
|
||||
match Self::get_type(sphinx_packet_size) {
|
||||
Ok(t) => Ok(t),
|
||||
Err(_) => Self::get_type(outfox_packet_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-19
@@ -7,49 +7,40 @@ use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{received} is not a valid packet mode tag")]
|
||||
pub struct InvalidPacketMode {
|
||||
pub struct InvalidPacketType {
|
||||
received: u8,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
pub enum PacketMode {
|
||||
pub enum PacketType {
|
||||
/// Represents 'normal' packet sent through the network that should be delayed by an appropriate
|
||||
/// value at each hop.
|
||||
#[default]
|
||||
Mix = 0,
|
||||
|
||||
/// Represents a VPN packet that should not be delayed and ideally cached pre-computed keys
|
||||
/// should be used for unwrapping data. Note that it does not offer the same level of anonymity.
|
||||
Vpn = 1,
|
||||
|
||||
/// Abusing this to add Outfox support
|
||||
Outfox = 2,
|
||||
}
|
||||
|
||||
impl PacketMode {
|
||||
impl PacketType {
|
||||
pub fn is_mix(self) -> bool {
|
||||
self == PacketMode::Mix
|
||||
}
|
||||
|
||||
pub fn is_old_vpn(self) -> bool {
|
||||
self == PacketMode::Vpn
|
||||
self == PacketType::Mix
|
||||
}
|
||||
|
||||
pub fn is_outfox(self) -> bool {
|
||||
self == PacketMode::Outfox
|
||||
self == PacketType::Outfox
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for PacketMode {
|
||||
type Error = InvalidPacketMode;
|
||||
impl TryFrom<u8> for PacketType {
|
||||
type Error = InvalidPacketType;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
_ if value == (PacketMode::Mix as u8) => Ok(Self::Mix),
|
||||
_ if value == (PacketMode::Vpn as u8) => Ok(Self::Vpn),
|
||||
_ if value == (PacketMode::Outfox as u8) => Ok(Self::Outfox),
|
||||
v => Err(InvalidPacketMode { received: v }),
|
||||
_ if value == (PacketType::Mix as u8) => Ok(Self::Mix),
|
||||
_ if value == (PacketType::Outfox as u8) => Ok(Self::Outfox),
|
||||
v => Err(InvalidPacketType { received: v }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::{ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
use nym_sphinx_types::builder::SphinxPacketBuilder;
|
||||
use nym_sphinx_types::{delays, Delay};
|
||||
use nym_sphinx_types::{delays, Delay, NymPacket};
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::convert::TryFrom;
|
||||
@@ -130,8 +130,11 @@ pub trait FragmentPreparer {
|
||||
self.generate_surb_ack(packet_sender, fragment_identifier, topology, ack_key)?;
|
||||
let ack_delay = surb_ack.expected_total_delay();
|
||||
|
||||
let packet_payload = NymsphinxPayloadBuilder::new(fragment, surb_ack)
|
||||
.build_reply(reply_surb.encryption_key());
|
||||
let packet_payload = match NymsphinxPayloadBuilder::new(fragment, surb_ack)
|
||||
.build_reply(reply_surb.encryption_key()) {
|
||||
Ok(payload) => payload,
|
||||
Err(_e) => return Err(NymTopologyError::PayloadBuilder)
|
||||
};
|
||||
|
||||
// the unwrap here is fine as the failures can only originate from attempting to use invalid payload lengths
|
||||
// and we just very carefully constructed a (presumably) valid one
|
||||
@@ -191,8 +194,11 @@ pub trait FragmentPreparer {
|
||||
self.generate_surb_ack(packet_sender, fragment_identifier, topology, ack_key)?;
|
||||
let ack_delay = surb_ack.expected_total_delay();
|
||||
|
||||
let packet_payload = NymsphinxPayloadBuilder::new(fragment, surb_ack)
|
||||
.build_regular(self.rng(), packet_recipient.encryption_key());
|
||||
let packet_payload = match NymsphinxPayloadBuilder::new(fragment, surb_ack)
|
||||
.build_regular(self.rng(), packet_recipient.encryption_key()) {
|
||||
Ok(payload) => payload,
|
||||
Err(_e) => return Err(NymTopologyError::PayloadBuilder)
|
||||
};
|
||||
|
||||
// generate pseudorandom route for the packet
|
||||
let hops = self.num_mix_hops();
|
||||
@@ -206,10 +212,10 @@ pub trait FragmentPreparer {
|
||||
|
||||
// create the actual sphinx packet here. With valid route and correct payload size,
|
||||
// there's absolutely no reason for this call to fail.
|
||||
let sphinx_packet = SphinxPacketBuilder::new()
|
||||
let sphinx_packet = NymPacket::Sphinx(SphinxPacketBuilder::new()
|
||||
.with_payload_size(packet_size.payload_size())
|
||||
.build_packet(packet_payload, &route, &destination, &delays)
|
||||
.unwrap();
|
||||
.unwrap());
|
||||
|
||||
// from the previously constructed route extract the first hop
|
||||
let first_hop_address =
|
||||
|
||||
@@ -6,7 +6,7 @@ use nym_crypto::asymmetric::encryption;
|
||||
use nym_crypto::shared_key::new_ephemeral_shared_key;
|
||||
use nym_crypto::symmetric::stream_cipher;
|
||||
use nym_crypto::symmetric::stream_cipher::CipherKey;
|
||||
use nym_sphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError};
|
||||
use nym_sphinx_anonymous_replies::SurbEncryptionKey;
|
||||
use nym_sphinx_chunking::fragment::Fragment;
|
||||
use nym_sphinx_params::{
|
||||
@@ -28,11 +28,11 @@ impl NymsphinxPayloadBuilder {
|
||||
self,
|
||||
packet_encryption_key: &CipherKey<C>,
|
||||
variant_data: impl IntoIterator<Item = u8>,
|
||||
) -> NymsphinxPayload
|
||||
) -> Result<NymsphinxPayload, SurbAckRecoveryError>
|
||||
where
|
||||
C: StreamCipher + KeyIvInit,
|
||||
{
|
||||
let (_, surb_ack_bytes) = self.surb_ack.prepare_for_sending();
|
||||
let (_, surb_ack_bytes) = self.surb_ack.prepare_for_sending()?;
|
||||
|
||||
let mut fragment_data = self.fragment.into_bytes();
|
||||
stream_cipher::encrypt_in_place::<C>(
|
||||
@@ -46,16 +46,19 @@ impl NymsphinxPayloadBuilder {
|
||||
// where variant-specific data is as follows:
|
||||
// for replies it would be the digest of the encryption key used
|
||||
// for 'regular' messages it would be the public component used in DH later used in the KDF
|
||||
NymsphinxPayload(
|
||||
Ok(NymsphinxPayload(
|
||||
surb_ack_bytes
|
||||
.into_iter()
|
||||
.chain(variant_data.into_iter())
|
||||
.chain(fragment_data.into_iter())
|
||||
.collect(),
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
pub fn build_reply(self, packet_encryption_key: &SurbEncryptionKey) -> NymsphinxPayload {
|
||||
pub fn build_reply(
|
||||
self,
|
||||
packet_encryption_key: &SurbEncryptionKey,
|
||||
) -> Result<NymsphinxPayload, SurbAckRecoveryError> {
|
||||
let key_digest = packet_encryption_key.compute_digest();
|
||||
self.build::<ReplySurbEncryptionAlgorithm>(
|
||||
packet_encryption_key.inner(),
|
||||
@@ -67,7 +70,7 @@ impl NymsphinxPayloadBuilder {
|
||||
self,
|
||||
rng: &mut R,
|
||||
recipient_encryption_key: &encryption::PublicKey,
|
||||
) -> NymsphinxPayload
|
||||
) -> Result<NymsphinxPayload, SurbAckRecoveryError>
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
|
||||
@@ -7,8 +7,6 @@ use nym_crypto::asymmetric::encryption;
|
||||
use nym_crypto::shared_key::recompute_shared_key;
|
||||
use nym_crypto::symmetric::stream_cipher;
|
||||
use nym_crypto::symmetric::stream_cipher::CipherKey;
|
||||
use nym_outfox::error::OutfoxError;
|
||||
use nym_outfox::lion::lion_transform_decrypt;
|
||||
use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx_anonymous_replies::SurbEncryptionKey;
|
||||
use nym_sphinx_chunking::fragment::Fragment;
|
||||
@@ -76,49 +74,6 @@ pub enum MessageRecoveryError {
|
||||
|
||||
#[error("Failed to recover message fragment - {0}")]
|
||||
FragmentRecoveryError(#[from] ChunkingError),
|
||||
|
||||
#[error("Outfox: {source}")]
|
||||
OutfoxRecoveryError {
|
||||
#[from]
|
||||
source: OutfoxError,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OutfoxMessageReceiver {
|
||||
reconstructor: MessageReconstructor,
|
||||
}
|
||||
|
||||
impl OutfoxMessageReceiver {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl MessageReceiver for OutfoxMessageReceiver {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn reconstructor(&mut self) -> &mut MessageReconstructor {
|
||||
&mut self.reconstructor
|
||||
}
|
||||
|
||||
fn num_mix_hops(&self) -> u8 {
|
||||
DEFAULT_NUM_MIX_HOPS
|
||||
}
|
||||
|
||||
fn decrypt_raw_message<C>(
|
||||
&self,
|
||||
message: &mut [u8],
|
||||
key: &CipherKey<C>,
|
||||
) -> Result<(), MessageRecoveryError>
|
||||
where
|
||||
C: StreamCipher + KeyIvInit,
|
||||
{
|
||||
lion_transform_decrypt(message, key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MessageReceiver {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub use nym_outfox::{error::OutfoxError, packet::OutfoxPacket, packet::OUTFOX_PACKET_OVERHEAD};
|
||||
pub use nym_outfox::{format::MIX_PARAMS_LEN, packet::OUTFOX_PACKET_OVERHEAD};
|
||||
// re-exporting types and constants available in sphinx
|
||||
use nym_outfox::packet::OutfoxPacket;
|
||||
pub use sphinx_packet::{
|
||||
constants::{
|
||||
self, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, MAX_PATH_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
@@ -14,9 +15,10 @@ pub use sphinx_packet::{
|
||||
payload::{Payload, PAYLOAD_OVERHEAD_SIZE},
|
||||
route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier},
|
||||
surb::{SURBMaterial, SURB},
|
||||
Error as SphinxError, ProcessedPacket, SphinxPacket,
|
||||
Error as SphinxError, ProcessedPacket,
|
||||
};
|
||||
use std::fmt;
|
||||
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
|
||||
use std::{array::TryFromSliceError, fmt};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@@ -26,6 +28,9 @@ pub enum NymPacketError {
|
||||
|
||||
#[error("Outfox error: {0}")]
|
||||
Outfox(#[from] nym_outfox::error::OutfoxError),
|
||||
|
||||
#[error("{0}")]
|
||||
FromSlice(#[from] TryFromSliceError),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@@ -50,6 +55,39 @@ impl fmt::Debug for NymPacket {
|
||||
}
|
||||
|
||||
impl NymPacket {
|
||||
pub fn sphinx_build<M: AsRef<[u8]>>(
|
||||
size: usize,
|
||||
message: M,
|
||||
route: &[Node],
|
||||
destination: &Destination,
|
||||
delays: &[Delay],
|
||||
) -> Result<NymPacket, NymPacketError> {
|
||||
Ok(NymPacket::Sphinx(
|
||||
SphinxPacketBuilder::new()
|
||||
.with_payload_size(size)
|
||||
.build_packet(message, route, destination, delays)?,
|
||||
))
|
||||
}
|
||||
pub fn sphinx_from_bytes(bytes: &[u8]) -> Result<NymPacket, NymPacketError> {
|
||||
Ok(NymPacket::Sphinx(SphinxPacket::from_bytes(bytes)?))
|
||||
}
|
||||
|
||||
pub fn outfox_build<M: AsRef<[u8]>>(
|
||||
payload: M,
|
||||
route: &[Node],
|
||||
size: Option<usize>,
|
||||
) -> Result<NymPacket, NymPacketError> {
|
||||
Ok(NymPacket::Outfox(OutfoxPacket::build(
|
||||
payload,
|
||||
route.try_into()?,
|
||||
size,
|
||||
)?))
|
||||
}
|
||||
|
||||
pub fn outfox_from_bytes(bytes: &[u8]) -> Result<NymPacket, NymPacketError> {
|
||||
Ok(NymPacket::Outfox(OutfoxPacket::try_from(bytes)?))
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
NymPacket::Sphinx(packet) => packet.len(),
|
||||
|
||||
@@ -33,4 +33,7 @@ pub enum NymTopologyError {
|
||||
total_nodes: usize,
|
||||
layer_distribution: Vec<(MixLayer, usize)>,
|
||||
},
|
||||
// We can't import SurbAckRecoveryError due to cyclic dependency, this is a bit dirty
|
||||
#[error("Could not build payload")]
|
||||
PayloadBuilder,
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::authentication::encrypted_address::EncryptedAddressBytes;
|
||||
use crate::iv::IV;
|
||||
use crate::registration::handshake::SharedKeys;
|
||||
use crate::{GatewayMacSize, PROTOCOL_VERSION};
|
||||
use log::error;
|
||||
use nym_coconut_interface::Credential;
|
||||
use nym_crypto::generic_array::typenum::Unsigned;
|
||||
use nym_crypto::hmac::recompute_keyed_hmac_and_verify_tag;
|
||||
@@ -290,7 +291,13 @@ impl BinaryRequest {
|
||||
pub fn into_encrypted_tagged_bytes(self, shared_key: &SharedKeys) -> Vec<u8> {
|
||||
match self {
|
||||
BinaryRequest::ForwardSphinx(mix_packet) => {
|
||||
let forwarding_data = mix_packet.into_bytes();
|
||||
let forwarding_data = match mix_packet.into_bytes() {
|
||||
Ok(mix_packet) => mix_packet,
|
||||
Err(e) => {
|
||||
error!("Could not convert packet to bytes: {e}");
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: it could be theoretically slightly more efficient if the data wasn't taken
|
||||
// by reference because then it makes a copy for encryption rather than do it in place
|
||||
|
||||
@@ -283,7 +283,7 @@ where
|
||||
&self,
|
||||
mix_packet: MixPacket,
|
||||
) -> Result<ServerResponse, RequestHandlingError> {
|
||||
let consumed_bandwidth = mix_packet.sphinx_packet().len() as i64;
|
||||
let consumed_bandwidth = mix_packet.packet().len() as i64;
|
||||
|
||||
let available_bandwidth = self.get_available_bandwidth().await?;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::node::node_statistics::UpdateSender;
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue};
|
||||
use nym_sphinx::{forwarding::packet::MixPacket, NymPacket};
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use std::io;
|
||||
use tokio::time::Instant;
|
||||
|
||||
@@ -58,14 +58,13 @@ where
|
||||
|
||||
fn forward_packet(&mut self, packet: MixPacket) {
|
||||
let next_hop = packet.next_hop();
|
||||
let packet_mode = packet.packet_mode();
|
||||
let sphinx_packet = packet.into_sphinx_packet();
|
||||
let packet_type = packet.packet_type();
|
||||
let packet = packet.into_packet();
|
||||
|
||||
if let Err(err) = self.mixnet_client.send_without_response(
|
||||
next_hop,
|
||||
NymPacket::Sphinx(sphinx_packet),
|
||||
packet_mode,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.mixnet_client
|
||||
.send_without_response(next_hop, packet, packet_type)
|
||||
{
|
||||
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)
|
||||
@@ -135,20 +134,20 @@ mod tests {
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use nym_sphinx::NymPacket;
|
||||
use nym_task::TaskManager;
|
||||
|
||||
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::PacketMode;
|
||||
use nym_sphinx_types::builder::SphinxPacketBuilder;
|
||||
use nym_sphinx_params::PacketType;
|
||||
use nym_sphinx_types::{
|
||||
crypto, Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
|
||||
SphinxPacket, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestClient {
|
||||
pub packets_sent: Arc<Mutex<Vec<(NymNodeRoutingAddress, NymPacket, PacketMode)>>>,
|
||||
pub packets_sent: Arc<Mutex<Vec<(NymNodeRoutingAddress, NymPacket, PacketType)>>>,
|
||||
}
|
||||
|
||||
impl nym_mixnet_client::SendWithoutResponse for TestClient {
|
||||
@@ -156,17 +155,17 @@ mod tests {
|
||||
&mut self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_mode: PacketMode,
|
||||
packet_type: PacketType,
|
||||
) -> io::Result<()> {
|
||||
self.packets_sent
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push((address, packet, packet_mode));
|
||||
.push((address, packet, packet_type));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn make_valid_sphinx_packet(size: PacketSize) -> SphinxPacket {
|
||||
fn make_valid_sphinx_packet(size: PacketSize) -> NymPacket {
|
||||
let (_, node1_pk) = crypto::keygen();
|
||||
let node1 = Node::new(
|
||||
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
|
||||
@@ -193,9 +192,7 @@ mod tests {
|
||||
SphinxDelay::new_from_nanos(42),
|
||||
SphinxDelay::new_from_nanos(42),
|
||||
];
|
||||
SphinxPacketBuilder::new()
|
||||
.with_payload_size(size.payload_size())
|
||||
.build_packet(b"foomp", &route, &destination, &delays)
|
||||
NymPacket::sphinx_build(size.payload_size(), b"foomp", &route, &destination, &delays)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -220,7 +217,7 @@ mod tests {
|
||||
let mix_packet = MixPacket::new(
|
||||
next_hop,
|
||||
make_valid_sphinx_packet(PacketSize::default()),
|
||||
PacketMode::default(),
|
||||
PacketType::default(),
|
||||
);
|
||||
let forward_instant = None;
|
||||
packet_sender
|
||||
|
||||
Generated
+1
@@ -3751,6 +3751,7 @@ dependencies = [
|
||||
"nym-sphinx-addressing",
|
||||
"nym-sphinx-params",
|
||||
"nym-sphinx-types",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -16,12 +16,7 @@ chacha20poly1305 = "0.10.1"
|
||||
getrandom = { version = "*", features = ["js"] }
|
||||
thiserror = "1"
|
||||
fastrand = "1.8"
|
||||
|
||||
sphinx-packet = "0.1.0"
|
||||
|
||||
[patch.crates-io]
|
||||
sphinx-packet = { path = "../../../../sphinx" }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.4"
|
||||
|
||||
@@ -49,8 +49,8 @@ impl OutfoxPacket {
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
pub fn build(
|
||||
payload: &[u8],
|
||||
pub fn build<M: AsRef<[u8]>>(
|
||||
payload: M,
|
||||
route: &[Node; 3],
|
||||
packet_size: Option<usize>,
|
||||
) -> Result<OutfoxPacket, OutfoxError> {
|
||||
@@ -58,9 +58,9 @@ impl OutfoxPacket {
|
||||
let packet_size = packet_size.unwrap_or(DEFAULT_PAYLOAD_SIZE);
|
||||
let mix_params = MixCreationParameters::new(packet_size as u16);
|
||||
|
||||
let padding = mix_params.total_packet_length() - payload.len();
|
||||
let padding = mix_params.total_packet_length() - payload.as_ref().len();
|
||||
let mut buffer = vec![0; padding];
|
||||
buffer.extend_from_slice(payload);
|
||||
buffer.extend_from_slice(payload.as_ref());
|
||||
|
||||
for (idx, node) in route.iter().rev().enumerate() {
|
||||
let (range, stage_params) = mix_params.get_stage_params(idx);
|
||||
|
||||
Reference in New Issue
Block a user