Files
nym/nym-node/src/node/lp/data/handler/messages/nymnode.rs
T

112 lines
3.6 KiB
Rust

// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_lp_data::packet::frame::{LpFrameAttributes, LpFrameHeader, LpFrameKind};
use nym_node_metrics::mixnet::PacketKind;
use nym_sphinx_forwarding::packet::MixPacketFormattingError;
use nym_sphinx_params::SphinxKeyRotation;
use nym_topology::NodeId;
use crate::node::lp::data::handler::{
error::LpDataHandlerError,
messages::{MixMessage, SphinxMixMessage},
};
/// Message types supported by nym-nodes with a gateway role.
#[derive(Debug, Clone, Copy)]
pub enum NymNodeMessage {
Mix(MixMessage),
ForwardSphinx(ForwardSphinxMixMessage),
ForwardOutfox(ForwardOutfoxMixMessage),
}
impl NymNodeMessage {
pub fn from_frame_header(header: LpFrameHeader) -> Result<Self, LpDataHandlerError> {
match header.kind {
LpFrameKind::SphinxPacket | LpFrameKind::OutfoxPacket => {
Ok(NymNodeMessage::Mix(MixMessage::from_frame_header(header)?))
}
LpFrameKind::ForwardSphinxPacket => Ok(NymNodeMessage::ForwardSphinx(
header.frame_attributes.try_into()?,
)),
LpFrameKind::ForwardOutfoxPacket => Ok(NymNodeMessage::ForwardOutfox(
header.frame_attributes.try_into()?,
)),
_ => Err(LpDataHandlerError::UnsupportedLpFrameKind { typ: header.kind }),
}
}
}
impl From<NymNodeMessage> for PacketKind {
fn from(value: NymNodeMessage) -> Self {
match value {
NymNodeMessage::Mix(msg) => msg.into(),
NymNodeMessage::ForwardSphinx(_) => PacketKind::LpSphinx,
NymNodeMessage::ForwardOutfox(_) => PacketKind::LpOutfox,
}
}
}
impl From<MixMessage> for NymNodeMessage {
fn from(value: MixMessage) -> Self {
NymNodeMessage::Mix(value)
}
}
impl From<NymNodeMessage> for LpFrameHeader {
fn from(value: NymNodeMessage) -> Self {
match value {
NymNodeMessage::Mix(msg) => msg.into(),
NymNodeMessage::ForwardSphinx(msg) => {
LpFrameHeader::new(LpFrameKind::ForwardSphinxPacket, msg)
}
NymNodeMessage::ForwardOutfox(msg) => {
LpFrameHeader::new(LpFrameKind::ForwardOutfoxPacket, msg)
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ForwardSphinxMixMessage {
pub key_rotation: SphinxKeyRotation,
pub next_hop: NodeId,
}
impl TryFrom<LpFrameAttributes> for ForwardSphinxMixMessage {
type Error = LpDataHandlerError;
fn try_from(value: LpFrameAttributes) -> Result<Self, Self::Error> {
let key_rotation = value[0]
.try_into()
.map_err(MixPacketFormattingError::InvalidKeyRotation)?;
// SAFETY : slice to array conversion with correct size
#[allow(clippy::unwrap_used)]
let next_hop = NodeId::from_be_bytes(value[1..5].try_into().unwrap());
Ok(ForwardSphinxMixMessage {
key_rotation,
next_hop,
})
}
}
impl From<ForwardSphinxMixMessage> for LpFrameAttributes {
fn from(value: ForwardSphinxMixMessage) -> Self {
let mut attrs = [0; 14];
attrs[0] = value.key_rotation as u8;
attrs[1..5].copy_from_slice(&value.next_hop.to_be_bytes());
attrs
}
}
impl From<ForwardSphinxMixMessage> for SphinxMixMessage {
fn from(value: ForwardSphinxMixMessage) -> Self {
SphinxMixMessage {
key_rotation: value.key_rotation,
}
}
}
// For now there are no differences. We can augment this variant when we will need it
pub type ForwardOutfoxMixMessage = ForwardSphinxMixMessage;