hopr_db_api/
protocol.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use async_trait::async_trait;
use std::{fmt::Debug, result::Result};

use hopr_crypto_types::prelude::*;
use hopr_internal_types::prelude::*;

use crate::prelude::DbError;

/// Trait defining all DB functionality needed by packet/acknowledgement processing pipeline.
#[async_trait]
pub trait HoprDbProtocolOperations {
    /// Processes the acknowledgements for the pending tickets
    ///
    /// There are three cases:
    /// 1. There is an unacknowledged ticket and we are awaiting a half key.
    /// 2. We were the creator of the packet, hence we do not wait for any half key
    /// 3. The acknowledgement is unexpected and stems from a protocol bug or an attacker
    async fn handle_acknowledgement(&self, ack: Acknowledgement, me: &ChainKeypair)
        -> crate::errors::Result<AckResult>;

    /// Process the data into an outgoing packet
    async fn to_send(
        &self,
        data: Box<[u8]>,
        me: ChainKeypair,
        path: Vec<OffchainPublicKey>,
        outgoing_ticket_win_prob: f64,
    ) -> Result<TransportPacketWithChainData, DbError>;

    /// Process the incoming packet into data
    #[allow(clippy::wrong_self_convention)]
    async fn from_recv(
        &self,
        data: Box<[u8]>,
        me: ChainKeypair,
        pkt_keypair: &OffchainKeypair,
        sender: OffchainPublicKey,
        outgoing_ticket_win_prob: f64,
    ) -> crate::errors::Result<TransportPacketWithChainData>;
}

#[allow(clippy::large_enum_variant)] // TODO: Uses too large objects
pub enum AckResult {
    Sender(HalfKeyChallenge),
    RelayerWinning(AcknowledgedTicket),
    RelayerLosing,
}

impl Debug for AckResult {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Sender(_) => f.debug_tuple("Sender").finish(),
            Self::RelayerWinning(_) => f.debug_tuple("RelayerWinning").finish(),
            Self::RelayerLosing => write!(f, "RelayerLosing"),
        }
    }
}

pub enum TransportPacketWithChainData {
    /// Packet is intended for us
    Final {
        packet_tag: PacketTag,
        previous_hop: OffchainPublicKey,
        plain_text: Box<[u8]>,
        ack: Acknowledgement,
    },
    /// Packet must be forwarded
    Forwarded {
        packet_tag: PacketTag,
        previous_hop: OffchainPublicKey,
        next_hop: OffchainPublicKey,
        data: Box<[u8]>,
        ack: Acknowledgement,
    },
    /// Packet that is being sent out by us
    Outgoing {
        next_hop: OffchainPublicKey,
        ack_challenge: HalfKeyChallenge,
        data: Box<[u8]>,
    },
}

#[allow(clippy::large_enum_variant)] // TODO: Uses too large objects
pub enum ResolvedAcknowledgement {
    Sending(HalfKeyChallenge),
    RelayingWin(AcknowledgedTicket),
    RelayingLoss(Hash),
}

impl From<ResolvedAcknowledgement> for AckResult {
    fn from(value: ResolvedAcknowledgement) -> Self {
        match value {
            ResolvedAcknowledgement::Sending(ack_challenge) => AckResult::Sender(ack_challenge),
            ResolvedAcknowledgement::RelayingWin(ack_ticket) => AckResult::RelayerWinning(ack_ticket),
            ResolvedAcknowledgement::RelayingLoss(_) => AckResult::RelayerLosing,
        }
    }
}