some PR review

This commit is contained in:
Simon Wicky
2026-05-20 11:33:44 +02:00
parent 95bec7422c
commit f505c29926
11 changed files with 29 additions and 58 deletions
+1 -1
View File
@@ -86,7 +86,7 @@ Implementors fill in `mix()`; everything else is provided by the [`MixnodeProces
- **Client-stage no-op marker traits** ([`NoOpReliability`], [`NoOpRoutingSecurity`], [`NoOpObfuscation`] in [`clients/helpers.rs`](src/clients/helpers.rs)) — implement these to opt out of a pipeline stage with zero overhead. Useful for stub or testing pipelines.
- **Wire-layer no-op marker traits** ([`NoOpWireWrapper`], [`NoOpWireUnwrapper`] in [`common/helpers.rs`](src/common/helpers.rs)) — collapse the entire wire layer (framing + transport, or their inverses) to a pass-through. Use these when your packet type is already self-contained on the wire (e.g. a Sphinx packet) and needs no extra framing or transport header. `NoOpWireWrapper` requires `Pkt: From<Vec<u8>>`; `NoOpWireUnwrapper` requires `Pkt: Into<Vec<u8>>` and `Mk: Default`.
- **`Pipeline` composition structs** (in [`clients/types.rs`](src/clients/types.rs) and [`mixnodes/types.rs`](src/mixnodes/types.rs)) — generic structs that aggregate one component per pipeline stage and provide blanket impls of the relevant supertraits, so you can build a working pipeline by plugging in any combination of stage implementations.
- **`Pipeline` composition structs** (in [`clients/types.rs`](src/clients/types.rs)) — generic structs that aggregate one component per pipeline stage and provide blanket impls of the relevant supertraits, so you can build a working pipeline by plugging in any combination of stage implementations.
- **[`ClientWrappingPipelineDriver`](src/clients/driver.rs)** — wraps a dyn-compatible client pipeline behind a tick-driven `tick(timestamp) -> Vec<(Pkt, NdId)>` interface, with an internal mpsc channel for application-supplied input payloads. Reads new input only when the internal buffer is empty so buffered packets do not stack additional latency on top.
[`NoOpReliability`]: src/clients/helpers.rs
+1 -1
View File
@@ -122,7 +122,7 @@ where
NdId: Clone,
{
// IMPORTANT NOTE : This fn can be not constant to allow e.g. flexible MTU
// However, every possible value must be able to accomodate the different overhead.
// However, every possible value must be able to accommodate the different overhead.
// If it doesn't, the pipeline becomes unusable
fn packet_size(&self) -> usize;
+3 -34
View File
@@ -22,7 +22,7 @@ use std::fmt::Debug;
pub mod clients;
pub mod common;
pub mod mixnodes;
pub mod nymnodes;
pub mod packet;
/// Convenience alias for [`TimedData`] when the payload is a raw byte buffer.
@@ -38,29 +38,12 @@ pub type PipelinePayload<Ts, Opts, NdId> = PipelineData<Ts, Vec<u8>, Opts, NdId>
/// pipeline. It is produced by [`clients::traits::Chunking`] and propagated
/// unchanged (or with the timestamp transformed) through every subsequent
/// pipeline stage until the packet is sent on the wire.
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct TimedData<Ts, D> {
pub timestamp: Ts,
pub data: D,
}
impl<Ts, D> Debug for TimedData<Ts, D>
where
D: Debug,
Ts: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "TimedData {{")?;
writeln!(f, " data:")?;
let data_debug = format!("{:#?}", &self.data);
for line in data_debug.lines() {
writeln!(f, " {}", line)?;
}
writeln!(f, " timestamp: {:#?},", &self.timestamp)?;
write!(f, "}}")
}
}
impl<Ts, D> TimedData<Ts, D> {
pub fn new(timestamp: Ts, data: D) -> Self {
TimedData { timestamp, data }
@@ -109,7 +92,7 @@ impl<Ts, D> TimedData<Ts, D> {
/// [`Framing`]: crate::common::traits::Framing
/// [`Transport`]: crate::common::traits::Transport
/// [`InputOptions`]: crate::clients::InputOptions
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct PipelineData<Ts, D, Opts, NdId> {
pub data: TimedData<Ts, D>,
pub options: Opts,
@@ -163,20 +146,6 @@ impl<Ts, D, Opts, NdId> PipelineData<Ts, D, Opts, NdId> {
}
}
impl<Ts, D, Opts, NdId> Debug for PipelineData<Ts, D, Opts, NdId>
where
D: Debug,
Ts: Debug,
NdId: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "PipelineData {{")?;
writeln!(f, " dst: {:#?}", &self.dst)?;
writeln!(f, " data: {:#?}", &self.data)?;
write!(f, "}}")
}
}
/// Convenience alias for [`PipelineData`] when no per-message pipeline options
/// are needed. Avoids duplicating the pipeline data structure.
pub type AddressedTimedData<Ts, D, NdId> = PipelineData<Ts, D, (), NdId>;
@@ -69,13 +69,13 @@ where
}
}
pub struct KcpReliability;
pub struct MockReliability;
impl KcpReliability {
impl MockReliability {
const HEADER: &[u8; 5] = b"0KCP0";
}
impl<Ts> Reliability<Ts, BasicOptions, u8> for KcpReliability {
impl<Ts> Reliability<Ts, BasicOptions, u8> for MockReliability {
const OVERHEAD_SIZE: usize = Self::HEADER.len();
fn reliable_encode(
&mut self,
@@ -94,15 +94,15 @@ impl<Ts> Reliability<Ts, BasicOptions, u8> for KcpReliability {
}
}
pub struct SphinxSecurity {
pub struct MockSphinxSecurity {
pub nb_frames: usize,
}
impl SphinxSecurity {
impl MockSphinxSecurity {
const HEADER: &[u8; 8] = b"0SPHINX0";
}
impl<Ts> RoutingSecurity<Ts, BasicOptions, u8> for SphinxSecurity {
impl<Ts> RoutingSecurity<Ts, BasicOptions, u8> for MockSphinxSecurity {
const OVERHEAD_SIZE: usize = Self::HEADER.len();
fn nb_frames(&self) -> usize {
@@ -167,13 +167,13 @@ impl Obfuscation<u32, BasicOptions, u8> for ReallyOddObfuscation {
}
}
pub struct LpFraming;
pub struct MockLpFraming;
impl LpFraming {
impl MockLpFraming {
const FRAME_ATTRIBUTES: &[u8; 14] = b"0LpFrameAttrs0";
}
impl<Ts> Framing<Ts, BasicOptions, u8> for LpFraming
impl<Ts> Framing<Ts, BasicOptions, u8> for MockLpFraming
where
Ts: Clone,
{
@@ -204,9 +204,9 @@ where
}
}
pub struct LpTransport;
pub struct MockLpTransport;
impl<Ts> Transport<Ts, LpPacket, u8> for LpTransport {
impl<Ts> Transport<Ts, LpPacket, u8> for MockLpTransport {
type Frame = LpFrame;
const OVERHEAD_SIZE: usize = LpHeader::SIZE;
fn to_transport_packet(
+6 -5
View File
@@ -4,7 +4,8 @@
use nym_lp_data::clients::{traits::ClientWrappingPipeline, types::Pipeline};
use crate::common::{
KcpReliability, KekwObfuscation, LpFraming, LpTransport, MockChunking, SphinxSecurity,
KekwObfuscation, MockChunking, MockLpFraming, MockLpTransport, MockReliability,
MockSphinxSecurity,
};
mod common;
@@ -16,13 +17,13 @@ fn empty_input_yields_empty_output() {
let mut mock_pipeline = Pipeline {
chunking: MockChunking,
reliability: KcpReliability,
security: SphinxSecurity {
reliability: MockReliability,
security: MockSphinxSecurity {
nb_frames: security_layer_nb_frames,
},
obfuscation: KekwObfuscation,
framing: LpFraming,
transport: LpTransport,
framing: MockLpFraming,
transport: MockLpTransport,
packet_size,
};
+1 -1
View File
@@ -81,7 +81,7 @@ fn main() -> anyhow::Result<()> {
break; // EOF
}
let text = line.trim_end_matches('\n').trim_end_matches('\r');
let text = line.trim();
let bytes = text.as_bytes();
// Prepend the destination node ID.
+1 -1
View File
@@ -11,7 +11,7 @@ use nym_lp_data::{
Framing, FramingUnwrap, Transport, TransportUnwrap, WireUnwrappingPipeline,
WireWrappingPipeline,
},
mixnodes::traits::MixnodeProcessingPipeline,
nymnodes::traits::MixnodeProcessingPipeline,
};
use crate::{
+1 -1
View File
@@ -9,7 +9,7 @@ use nym_crypto::asymmetric::x25519;
use nym_lp_data::{
AddressedTimedData, AddressedTimedPayload, TimedPayload,
common::helpers::{NoOpWireUnwrapper, NoOpWireWrapper},
mixnodes::traits::MixnodeProcessingPipeline,
nymnodes::traits::MixnodeProcessingPipeline,
};
use nym_sphinx::SphinxPacket;
+4 -3
View File
@@ -62,13 +62,14 @@ impl SimplePacket {
///
/// Layout: 16 bytes UUID (LE) + 48 bytes payload = 64 bytes total.
const SIZE: usize = 64;
const UUID_SIZE: usize = 16;
/// Create a new [`SimplePacket`] with a freshly generated UUID v4 and the
/// provided 48-byte payload.
///
/// The payload array is exactly `SIZE - 16 = 48` bytes so that the packet
/// serialises to exactly [`SimplePacket::SIZE`] bytes.
pub fn new(data: [u8; Self::SIZE - 16]) -> Self {
pub fn new(data: [u8; Self::SIZE - Self::UUID_SIZE]) -> Self {
Self {
id: Uuid::new_v4(),
data: data.to_vec(),
@@ -114,8 +115,8 @@ impl SimplePacket {
));
}
#[allow(clippy::unwrap_used)]
let uuid = Uuid::from_bytes_le(bytes[0..16].try_into().unwrap());
let data = bytes[16..Self::SIZE].to_vec();
let uuid = Uuid::from_bytes_le(bytes[0..Self::UUID_SIZE].try_into().unwrap());
let data = bytes[Self::UUID_SIZE..Self::SIZE].to_vec();
Ok(SimplePacket { id: uuid, data })
}
}