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 = HoprKeyIdent;
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/// Type alias for 32-bit HOPR Offchain Public Key Identifier.
71pub type HoprKeyIdent = KeyIdent<4>;
72
73/// Single Use Reply Block representation for HOPR protocol.
74pub type HoprSurb = SURB<HoprSphinxSuite, HoprSphinxHeaderSpec>;
75
76/// Type alias for identifiable [`ReplyOpener`].
77pub type HoprReplyOpener = (types::HoprSurbId, ReplyOpener);
78
79/// Size of the maximum packet payload.
80///
81/// Adjust this value to change the maximum packet size.
82/// The calculation here is based on the fact that libp2p Stream over QUIC
83/// leaves space for 1460 bytes in the packet payload.
84///
85/// **DO NOT USE this value for calculations outside of this crate: use `HoprPacket::PAYLOAD_SIZE` instead!**
86pub(crate) const PAYLOAD_SIZE_INT: usize = DefaultSphinxPacketSize::USIZE - 1; // minus padding byte
87
88#[cfg(test)]
89mod tests {
90    use hopr_crypto_sphinx::prelude::MetaPacket;
91
92    use super::*;
93    use crate::packet::HoprPacket;
94
95    #[test]
96    fn header_and_packet_lengths() {
97        let hopr_packet_len = HoprPacket::SIZE;
98        assert_eq!(
99            MetaPacket::<HoprSphinxSuite, HoprSphinxHeaderSpec, PAYLOAD_SIZE_INT>::PACKET_LEN + Ticket::SIZE,
100            hopr_packet_len
101        );
102
103        assert!(
104            hopr_packet_len <= 1492 - 32, // 32 bytes was measured as the libp2p QUIC overhead
105            "HOPR packet of {hopr_packet_len} bytes must fit within a layer 4 packet with libp2p overhead"
106        );
107    }
108
109    #[test]
110    fn packet_length() {
111        let packet_len = HoprPacket::SIZE;
112        assert_eq!(packet_len, 422 + PAYLOAD_SIZE_INT);
113    }
114
115    #[test]
116    fn header_length() {
117        let header_len = HoprSphinxHeaderSpec::HEADER_LEN;
118        assert_eq!(header_len, 241);
119    }
120
121    #[test]
122    fn surb_length() {
123        let surb_len = HoprSurb::SIZE;
124        assert_eq!(surb_len, 395);
125        assert!(HoprPacket::PAYLOAD_SIZE > surb_len * 2);
126    }
127
128    #[test]
129    fn max_surbs_per_packet_must_be_at_least_2() {
130        const _: () = {
131            assert!(HoprPacket::MAX_SURBS_IN_PACKET >= 2);
132        };
133    }
134}