hopr_crypto_packet/
lib.rs

1//! # core-packet
2//!
3//! This crate contains the main packet processing functionality for the HOPR protocol.
4//! It implements the following important protocol building blocks:
5//!
6//! - HOPR specific instantiation of the SPHINX packet format
7//! - Proof of Relay
8//!
9//! Finally, it also implements a utility function which is used to validate tickets (module `validation`).
10//!
11//! The currently used implementation is selected using the [`HoprSphinxSuite`] type in the `packet` module.
12//!
13//! The implementation can be easily extended for different elliptic curves (or even arithmetic multiplicative groups).
14//! In particular, as soon as there is a way to represent `Ed448` PeerIDs, it would be straightforward to create e.g.
15//! `X448Suite`.
16//!
17//! This crate implements [RFC-0003](https://github.com/hoprnet/rfc/tree/main/rfcs/RFC-0003-hopr-packet-protocol).
18
19use hopr_crypto_sphinx::prelude::*;
20use hopr_internal_types::prelude::*;
21use hopr_primitive_types::prelude::*;
22
23/// Lists all errors in this crate.
24pub mod errors;
25/// Implements the overlay packet intermediary object.
26mod packet;
27/// Implements the Proof of Relay.
28mod por;
29/// Contains various helper types.
30mod types;
31/// Implements ticket validation logic.
32mod validation;
33
34#[doc(hidden)]
35pub mod prelude {
36    pub use super::*;
37    pub use crate::{
38        packet::{
39            HoprForwardedPacket, HoprIncomingPacket, HoprOutgoingPacket, HoprPacket, PacketRouting, PartialHoprPacket,
40        },
41        types::{HoprSenderId, HoprSurbId, PacketSignal, PacketSignals},
42        validation::validate_unacknowledged_ticket,
43    };
44}
45
46pub use hopr_crypto_sphinx::prelude::{KeyIdMapper, ReplyOpener};
47
48/// Currently used public key cipher suite for Sphinx.
49///
50/// This is currently the [`Ed25519Suite`], because it is faster than [`X25519Suite`].
51pub type HoprSphinxSuite = Ed25519Suite;
52
53/// Current Sphinx header specification for the HOPR protocol.
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56pub struct HoprSphinxHeaderSpec;
57
58impl SphinxHeaderSpec for HoprSphinxHeaderSpec {
59    type KeyId = KeyIdent<4>;
60    type PRG = hopr_crypto_types::primitives::ChaCha20;
61    type PacketReceiverData = types::HoprSenderId;
62    type Pseudonym = HoprPseudonym;
63    type RelayerData = por::ProofOfRelayString;
64    type SurbReceiverData = por::SurbReceiverInfo;
65    type UH = hopr_crypto_types::primitives::Poly1305;
66
67    const MAX_HOPS: std::num::NonZeroUsize = std::num::NonZeroUsize::new(INTERMEDIATE_HOPS + 1).unwrap();
68}
69
70/// Single Use Reply Block representation for HOPR protocol.
71pub type HoprSurb = SURB<HoprSphinxSuite, HoprSphinxHeaderSpec>;
72
73/// Type alias for identifiable [`ReplyOpener`].
74pub type HoprReplyOpener = (types::HoprSurbId, ReplyOpener);
75
76/// Size of the maximum packet payload.
77///
78/// Adjust this value to change the maximum packet size.
79/// The calculation here is based on the fact that libp2p Stream over QUIC
80/// leaves space for 1460 bytes in the packet payload.
81///
82/// **DO NOT USE this value for calculations outside of this crate: use `HoprPacket::PAYLOAD_SIZE` instead!**
83pub(crate) const PAYLOAD_SIZE_INT: usize = 1021;
84
85#[cfg(test)]
86mod tests {
87    use hopr_crypto_sphinx::prelude::MetaPacket;
88
89    use super::*;
90    use crate::packet::HoprPacket;
91
92    #[test]
93    fn header_and_packet_lengths() {
94        let hopr_packet_len = HoprPacket::SIZE;
95        assert_eq!(
96            MetaPacket::<HoprSphinxSuite, HoprSphinxHeaderSpec, PAYLOAD_SIZE_INT>::PACKET_LEN + Ticket::SIZE,
97            hopr_packet_len
98        );
99
100        assert!(
101            hopr_packet_len <= 1492 - 32, // 32 bytes was measured as the libp2p QUIC overhead
102            "HOPR packet of {hopr_packet_len} bytes must fit within a layer 4 packet with libp2p overhead"
103        );
104    }
105
106    #[test]
107    fn packet_length() {
108        let packet_len = HoprPacket::SIZE;
109        assert_eq!(packet_len, 438 + PAYLOAD_SIZE_INT);
110    }
111
112    #[test]
113    fn header_length() {
114        let header_len = HoprSphinxHeaderSpec::HEADER_LEN;
115        assert_eq!(header_len, 241);
116    }
117
118    #[test]
119    fn surb_length() {
120        let surb_len = HoprSurb::SIZE;
121        assert_eq!(surb_len, 395);
122        assert!(HoprPacket::PAYLOAD_SIZE > surb_len * 2);
123    }
124
125    #[test]
126    fn max_surbs_per_packet_must_be_at_least_2() {
127        const _: () = {
128            assert!(HoprPacket::MAX_SURBS_IN_PACKET >= 2);
129        };
130    }
131}