hopr_db_api/
protocol.rs

1use async_trait::async_trait;
2use hopr_crypto_packet::prelude::PacketSignals;
3pub use hopr_crypto_packet::{HoprSurb, prelude::HoprSenderId};
4use hopr_crypto_types::prelude::*;
5use hopr_internal_types::prelude::*;
6use hopr_network_types::prelude::{ResolvedTransportRouting, SurbMatcher};
7use hopr_primitive_types::balance::HoprBalance;
8
9use crate::errors::Result;
10
11/// Contains a SURB found in the SURB ring buffer via [`HoprDbProtocolOperations::find_surb`].
12#[derive(Debug)]
13pub struct FoundSurb {
14    /// Complete sender ID of the SURB.
15    pub sender_id: HoprSenderId,
16    /// The SURB itself.
17    pub surb: HoprSurb,
18    /// Number of SURBs remaining in the ring buffer with the same pseudonym.
19    pub remaining: usize,
20}
21
22/// Configuration for the SURB cache.
23#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
24pub struct SurbCacheConfig {
25    /// Size of the SURB ring buffer per pseudonym.
26    pub rb_capacity: usize,
27    /// Threshold for the number of SURBs in the ring buffer, below which it is
28    /// considered low ("SURB distress").
29    pub distress_threshold: usize,
30}
31
32/// Trait defining all DB functionality needed by a packet/acknowledgement processing pipeline.
33#[async_trait]
34pub trait HoprDbProtocolOperations {
35    /// Processes the acknowledgements for the pending tickets
36    ///
37    /// There are three cases:
38    /// 1. There is an unacknowledged ticket and we are awaiting a half key.
39    /// 2. We were the creator of the packet, hence we do not wait for any half key
40    /// 3. The acknowledgement is unexpected and stems from a protocol bug or an attacker
41    async fn handle_acknowledgement(&self, ack: VerifiedAcknowledgement) -> Result<()>;
42
43    /// Loads (presumably cached) value of the network's minimum winning probability from the DB.
44    async fn get_network_winning_probability(&self) -> Result<WinningProbability>;
45
46    /// Loads (presumably cached) value of the network's minimum ticket price from the DB.
47    async fn get_network_ticket_price(&self) -> Result<HoprBalance>;
48
49    /// Attempts to find SURB and its ID given the [`SurbMatcher`].
50    async fn find_surb(&self, matcher: SurbMatcher) -> Result<FoundSurb>;
51
52    /// Returns the SURB cache configuration.
53    fn get_surb_config(&self) -> SurbCacheConfig;
54
55    /// Process the data into an outgoing packet that is not going to be acknowledged.
56    async fn to_send_no_ack(&self, data: Box<[u8]>, destination: OffchainPublicKey) -> Result<OutgoingPacket>;
57
58    /// Process the data into an outgoing packet
59    async fn to_send(
60        &self,
61        data: Box<[u8]>,
62        routing: ResolvedTransportRouting,
63        outgoing_ticket_win_prob: WinningProbability,
64        outgoing_ticket_price: HoprBalance,
65        signals: PacketSignals,
66    ) -> Result<OutgoingPacket>;
67
68    /// Process the incoming packet into data
69    #[allow(clippy::wrong_self_convention)]
70    async fn from_recv(
71        &self,
72        data: Box<[u8]>,
73        pkt_keypair: &OffchainKeypair,
74        sender: OffchainPublicKey,
75        outgoing_ticket_win_prob: WinningProbability,
76        outgoing_ticket_price: HoprBalance,
77    ) -> Result<IncomingPacket>;
78}
79
80/// Contains some miscellaneous information about a received packet.
81#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
82pub struct AuxiliaryPacketInfo {
83    /// Packet signals that the packet carried.
84    ///
85    /// Zero if no signal flags were specified.
86    pub packet_signals: PacketSignals,
87    /// Number of SURBs that the packet carried.
88    pub num_surbs: usize,
89}
90
91#[allow(clippy::large_enum_variant)] // TODO: Uses too large objects
92pub enum IncomingPacket {
93    /// Packet is intended for us
94    Final {
95        packet_tag: PacketTag,
96        previous_hop: OffchainPublicKey,
97        sender: HoprPseudonym,
98        plain_text: Box<[u8]>,
99        ack_key: HalfKey,
100        info: AuxiliaryPacketInfo,
101    },
102    /// Packet must be forwarded
103    Forwarded {
104        packet_tag: PacketTag,
105        previous_hop: OffchainPublicKey,
106        next_hop: OffchainPublicKey,
107        data: Box<[u8]>,
108        /// Acknowledgement payload to be sent to the previous hop
109        ack_key: HalfKey,
110    },
111    /// The packet contains an acknowledgement of a delivered packet.
112    Acknowledgement {
113        packet_tag: PacketTag,
114        previous_hop: OffchainPublicKey,
115        ack: Acknowledgement,
116    },
117}
118
119/// Packet that is being sent out by us
120pub struct OutgoingPacket {
121    pub next_hop: OffchainPublicKey,
122    pub ack_challenge: HalfKeyChallenge,
123    pub data: Box<[u8]>,
124}
125
126impl std::fmt::Debug for OutgoingPacket {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        f.debug_struct("OutgoingPacket")
129            .field("next_hop", &self.next_hop)
130            .field("ack_challenge", &self.ack_challenge)
131            .finish_non_exhaustive()
132    }
133}
134
135#[allow(clippy::large_enum_variant)] // TODO: Uses too large objects
136pub enum ResolvedAcknowledgement {
137    Sending(VerifiedAcknowledgement),
138    RelayingWin(AcknowledgedTicket),
139    RelayingLoss(Hash),
140}