Skip to main content

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
19pub mod sphinx;
20use hopr_types::{internal::prelude::*, primitive::prelude::*};
21use sphinx::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 hopr_types::internal::routing::{HoprSenderId, HoprSurbId};
37
38    pub use super::*;
39    pub use crate::{
40        packet::{
41            HoprForwardedPacket, HoprIncomingPacket, HoprOutgoingPacket, HoprPacket, PacketRouting, PartialHoprPacket,
42        },
43        types::{PacketSignal, PacketSignals},
44        validation::validate_unacknowledged_ticket,
45    };
46}
47
48use hopr_types::internal::routing;
49pub use sphinx::prelude::{ProtocolKeyIdMapper, ReplyOpener};
50
51/// Currently used public key cipher suite for Sphinx.
52///
53/// This is currently the [`Ed25519Suite`], because it is faster than `X25519Suite`.
54pub type HoprSphinxSuite = Ed25519Suite;
55
56/// Current Sphinx header specification for the HOPR protocol.
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59pub struct HoprSphinxHeaderSpec;
60
61impl SphinxHeaderSpec for HoprSphinxHeaderSpec {
62    type KeyId = HoprKeyIdent;
63    type PRG = hopr_types::crypto::primitives::ChaCha20;
64    type PacketReceiverData = routing::HoprSenderId;
65    type Pseudonym = HoprPseudonym;
66    type RelayerData = por::ProofOfRelayString;
67    type SurbReceiverData = por::SurbReceiverInfo;
68    type UH = hopr_types::crypto::primitives::Poly1305;
69
70    const MAX_HOPS: std::num::NonZeroUsize = std::num::NonZeroUsize::new(INTERMEDIATE_HOPS + 1).unwrap();
71}
72
73/// Type alias for 32-bit HOPR Offchain Public Key Identifier.
74pub type HoprKeyIdent = KeyIdent<4>;
75
76/// Single Use Reply Block representation for HOPR protocol.
77pub type HoprSurb = SURB<HoprSphinxSuite, HoprSphinxHeaderSpec>;
78
79/// Type alias for identifiable [`ReplyOpener`].
80pub type HoprReplyOpener = (routing::HoprSurbId, ReplyOpener);
81
82/// Size of the maximum packet payload.
83///
84/// Adjust this value to change the maximum packet size.
85/// The calculation here is based on the fact that libp2p Stream over QUIC
86/// leaves space for 1460 bytes in the packet payload.
87///
88/// **DO NOT USE this value for calculations outside of this crate: use `HoprPacket::PAYLOAD_SIZE` instead!**
89pub(crate) const PAYLOAD_SIZE_INT: usize = DefaultSphinxPacketSize::USIZE - 1; // minus padding byte
90
91#[cfg(test)]
92mod tests {
93    use sphinx::prelude::MetaPacket;
94
95    use super::*;
96    use crate::packet::HoprPacket;
97
98    #[test]
99    fn header_and_packet_lengths() {
100        let hopr_packet_len = HoprPacket::SIZE;
101        assert_eq!(
102            MetaPacket::<HoprSphinxSuite, HoprSphinxHeaderSpec, PAYLOAD_SIZE_INT>::PACKET_LEN + Ticket::SIZE,
103            hopr_packet_len
104        );
105
106        assert!(
107            hopr_packet_len <= 1492 - 32, // 32 bytes was measured as the libp2p QUIC overhead
108            "HOPR packet of {hopr_packet_len} bytes must fit within a layer 4 packet with libp2p overhead"
109        );
110    }
111
112    #[test]
113    fn packet_length() {
114        let packet_len = HoprPacket::SIZE;
115        assert_eq!(packet_len, 422 + PAYLOAD_SIZE_INT);
116    }
117
118    #[test]
119    fn header_length() {
120        let header_len = HoprSphinxHeaderSpec::HEADER_LEN;
121        assert_eq!(header_len, 241);
122    }
123
124    #[test]
125    fn surb_length() {
126        let surb_len = HoprSurb::SIZE;
127        assert_eq!(surb_len, 395);
128        assert!(HoprPacket::PAYLOAD_SIZE > surb_len * 2);
129    }
130
131    #[test]
132    fn max_surbs_per_packet_must_be_at_least_2() {
133        const _: () = {
134            assert!(HoprPacket::MAX_SURBS_IN_PACKET >= 2);
135        };
136    }
137}