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},
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.
49pub type HoprSphinxSuite = X25519Suite;
50
51/// Current Sphinx header specification for the HOPR protocol.
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
54pub struct HoprSphinxHeaderSpec;
55
56impl SphinxHeaderSpec for HoprSphinxHeaderSpec {
57    type KeyId = KeyIdent<4>;
58    type PRG = hopr_crypto_types::primitives::ChaCha20;
59    type PacketReceiverData = types::HoprSenderId;
60    type Pseudonym = HoprPseudonym;
61    type RelayerData = por::ProofOfRelayString;
62    type SurbReceiverData = por::SurbReceiverInfo;
63    type UH = hopr_crypto_types::primitives::Poly1305;
64
65    const MAX_HOPS: std::num::NonZeroUsize = std::num::NonZeroUsize::new(INTERMEDIATE_HOPS + 1).unwrap();
66}
67
68/// Single Use Reply Block representation for HOPR protocol.
69pub type HoprSurb = SURB<HoprSphinxSuite, HoprSphinxHeaderSpec>;
70
71/// Type alias for identifiable [`ReplyOpener`].
72pub type HoprReplyOpener = (types::HoprSurbId, ReplyOpener);
73
74/// Size of the maximum packet payload.
75///
76/// Adjust this value to change the maximum packet size.
77/// The calculation here is based on the fact that libp2p Stream over QUIC
78/// leaves space for 1460 bytes in the packet payload.
79///
80/// **DO NOT USE this value for calculations outside of this crate: use `HoprPacket::PAYLOAD_SIZE` instead!**
81pub(crate) const PAYLOAD_SIZE_INT: usize = 1021;
82
83#[cfg(test)]
84mod tests {
85    use hopr_crypto_sphinx::prelude::MetaPacket;
86
87    use super::*;
88    use crate::packet::HoprPacket;
89
90    #[test]
91    fn header_and_packet_lengths() {
92        let hopr_packet_len = HoprPacket::SIZE;
93        assert_eq!(
94            MetaPacket::<HoprSphinxSuite, HoprSphinxHeaderSpec, PAYLOAD_SIZE_INT>::PACKET_LEN + Ticket::SIZE,
95            hopr_packet_len
96        );
97
98        assert!(
99            hopr_packet_len <= 1492 - 32, // 32 bytes was measured as the libp2p QUIC overhead
100            "HOPR packet of {hopr_packet_len} bytes must fit within a layer 4 packet with libp2p overhead"
101        );
102    }
103
104    #[test]
105    fn packet_length() {
106        let packet_len = HoprPacket::SIZE;
107        assert_eq!(packet_len, 438 + PAYLOAD_SIZE_INT);
108    }
109
110    #[test]
111    fn header_length() {
112        let header_len = HoprSphinxHeaderSpec::HEADER_LEN;
113        assert_eq!(header_len, 241);
114    }
115
116    #[test]
117    fn surb_length() {
118        let surb_len = HoprSurb::SIZE;
119        assert_eq!(surb_len, 395);
120        assert!(HoprPacket::PAYLOAD_SIZE > surb_len * 2);
121    }
122
123    #[test]
124    fn max_surbs_per_packet_must_be_at_least_2() {
125        const _: () = {
126            assert!(HoprPacket::MAX_SURBS_IN_PACKET >= 2);
127        };
128    }
129}