1use std::{array::TryFromSliceError, fmt};
5use thiserror::Error;
6
7#[cfg(feature = "outfox")]
8pub use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
9
10#[cfg(feature = "sphinx")]
11pub use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
12
13#[cfg(feature = "outfox")]
14pub use nym_outfox::{
15 constants::MIN_PACKET_SIZE, constants::MIX_PARAMS_LEN, constants::OUTFOX_PACKET_OVERHEAD,
16 error::OutfoxError,
17};
18#[cfg(feature = "sphinx")]
21pub use sphinx_packet::{
22 Error as SphinxError, ProcessedPacket, ProcessedPacketData,
23 constants::{
24 self, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, MAX_PATH_LENGTH, NODE_ADDRESS_LENGTH,
25 PAYLOAD_KEY_SIZE, REPLAY_TAG_SIZE,
26 },
27 crypto::{self, PrivateKey, PublicKey},
28 header::{self, HEADER_SIZE, ProcessedHeader, SphinxHeader, delays, delays::Delay},
29 packet::builder::DEFAULT_PAYLOAD_SIZE,
30 payload::{
31 PAYLOAD_OVERHEAD_SIZE, Payload,
32 key::{PayloadKey, PayloadKeySeed},
33 },
34 route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier},
35 surb::{SURB, SURBMaterial},
36 version::*,
37};
38
39#[derive(Error, Debug)]
40pub enum NymPacketError {
41 #[error("Sphinx error: {0}")]
42 #[cfg(feature = "sphinx")]
43 Sphinx(#[from] sphinx_packet::Error),
44
45 #[error("Outfox error: {0}")]
46 #[cfg(feature = "outfox")]
47 Outfox(#[from] nym_outfox::error::OutfoxError),
48
49 #[error("{0}")]
50 FromSlice(#[from] TryFromSliceError),
51}
52
53#[allow(clippy::large_enum_variant)]
55pub enum NymPacket {
56 #[cfg(feature = "sphinx")]
57 Sphinx(SphinxPacket),
58 #[cfg(feature = "outfox")]
59 Outfox(OutfoxPacket),
60}
61
62pub enum NymProcessedPacket {
63 #[cfg(feature = "sphinx")]
64 Sphinx(ProcessedPacket),
65 #[cfg(feature = "outfox")]
66 Outfox(OutfoxProcessedPacket),
67}
68
69impl fmt::Debug for NymPacket {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 #[allow(unreachable_patterns)]
72 match &self {
73 #[cfg(feature = "sphinx")]
74 NymPacket::Sphinx(packet) => f
75 .debug_struct("NymPacket::Sphinx")
76 .field("len", &packet.len())
77 .finish(),
78 #[cfg(feature = "outfox")]
79 NymPacket::Outfox(packet) => f
80 .debug_struct("NymPacket::Outfox")
81 .field("len", &packet.len())
82 .finish(),
83 _ => write!(f, ""),
84 }
85 }
86}
87
88impl NymPacket {
89 #[cfg(feature = "sphinx")]
90 pub fn sphinx_build<M: AsRef<[u8]>>(
91 use_legacy_sphinx_format: bool,
92 size: usize,
93 message: M,
94 route: &[Node],
95 destination: &Destination,
96 delays: &[Delay],
97 ) -> Result<NymPacket, NymPacketError> {
98 let mut builder = SphinxPacketBuilder::new().with_payload_size(size);
99
100 if use_legacy_sphinx_format {
101 builder = builder.with_version(X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION)
102 };
103
104 Ok(NymPacket::Sphinx(builder.build_packet(
105 message,
106 route,
107 destination,
108 delays,
109 )?))
110 }
111 #[cfg(feature = "sphinx")]
112 pub fn sphinx_from_bytes(bytes: &[u8]) -> Result<NymPacket, NymPacketError> {
113 Ok(NymPacket::Sphinx(SphinxPacket::from_bytes(bytes)?))
114 }
115
116 #[cfg(feature = "outfox")]
117 pub fn outfox_build<M: AsRef<[u8]>>(
118 payload: M,
119 route: &[Node],
120 destination: &Destination,
121 size: Option<usize>,
122 ) -> Result<NymPacket, NymPacketError> {
123 Ok(NymPacket::Outfox(OutfoxPacket::build(
124 payload,
125 route.try_into()?,
126 destination,
127 size,
128 )?))
129 }
130
131 #[cfg(feature = "outfox")]
132 pub fn outfox_from_bytes(bytes: &[u8]) -> Result<NymPacket, NymPacketError> {
133 Ok(NymPacket::Outfox(OutfoxPacket::try_from(bytes)?))
134 }
135
136 pub fn len(&self) -> usize {
137 #[allow(unreachable_patterns)]
138 match self {
139 #[cfg(feature = "sphinx")]
140 NymPacket::Sphinx(packet) => packet.len(),
141 #[cfg(feature = "outfox")]
142 NymPacket::Outfox(packet) => packet.len(),
143 _ => 0,
144 }
145 }
146
147 pub fn is_empty(&self) -> bool {
148 self.len() == 0
149 }
150
151 pub fn to_bytes(&self) -> Result<Vec<u8>, NymPacketError> {
152 #[allow(unreachable_patterns)]
153 match self {
154 #[cfg(feature = "sphinx")]
155 NymPacket::Sphinx(packet) => Ok(packet.to_bytes()),
156 #[cfg(feature = "outfox")]
157 NymPacket::Outfox(packet) => Ok(packet.to_bytes()?),
158 _ => Ok(vec![]),
159 }
160 }
161
162 #[cfg(feature = "sphinx")]
163 pub fn process(
164 self,
165 node_secret_key: &PrivateKey,
166 ) -> Result<NymProcessedPacket, NymPacketError> {
167 match self {
168 NymPacket::Sphinx(packet) => {
169 Ok(NymProcessedPacket::Sphinx(packet.process(node_secret_key)?))
170 }
171 #[cfg(feature = "outfox")]
172 NymPacket::Outfox(mut packet) => {
173 let next_address = packet.decode_next_layer(node_secret_key)?;
174 Ok(NymProcessedPacket::Outfox(OutfoxProcessedPacket::new(
175 packet,
176 next_address,
177 )))
178 }
179 }
180 }
181
182 #[cfg(feature = "sphinx")]
183 #[allow(unreachable_patterns)]
184 pub fn sphinx_packet_ref(&self) -> Option<&SphinxPacket> {
185 match self {
186 NymPacket::Sphinx(packet) => Some(packet),
187 _ => None,
188 }
189 }
190
191 #[cfg(feature = "sphinx")]
192 #[allow(unreachable_patterns)]
193 pub fn to_sphinx_packet(self) -> Option<SphinxPacket> {
194 match self {
195 NymPacket::Sphinx(packet) => Some(packet),
196 _ => None,
197 }
198 }
199
200 #[cfg(feature = "sphinx")]
201 pub fn is_sphinx(&self) -> bool {
202 matches!(self, NymPacket::Sphinx(_))
203 }
204}