hopr_internal_types/
protocol.rs

1use hopr_crypto_random::Randomizable;
2use hopr_crypto_types::prelude::*;
3use hopr_primitive_types::prelude::*;
4
5use crate::{
6    errors::{CoreTypesError, Result},
7    prelude::UnacknowledgedTicket,
8};
9
10/// Number of intermediate hops: 3 relayers and 1 destination
11pub const INTERMEDIATE_HOPS: usize = 3;
12
13/// Default required minimum incoming ticket winning probability
14pub const DEFAULT_MINIMUM_INCOMING_TICKET_WIN_PROB: f64 = 1.0;
15
16/// Default maximum incoming ticket winning probability, above which tickets will not be accepted
17/// due to privacy.
18pub const DEFAULT_MAXIMUM_INCOMING_TICKET_WIN_PROB: f64 = 1.0; // TODO: change this in 3.0
19
20/// Alias for the [`Pseudonym`](`hopr_crypto_types::types::Pseudonym`) used in the HOPR protocol.
21pub type HoprPseudonym = SimplePseudonym;
22
23/// Unverified packet acknowledgement.
24///
25/// This acknowledgement can be serialized and deserialized to be sent over the wire.
26///
27/// To retrieve useful data, it has to be [verified](`Acknowledgement::verify`) using the public
28/// key of its sender.
29#[derive(Copy, Clone, Debug, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct Acknowledgement(#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))] [u8; Self::SIZE]);
32
33impl AsRef<[u8]> for Acknowledgement {
34    fn as_ref(&self) -> &[u8] {
35        &self.0
36    }
37}
38
39impl TryFrom<&[u8]> for Acknowledgement {
40    type Error = GeneralError;
41
42    fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
43        Ok(Self(
44            value
45                .try_into()
46                .map_err(|_| GeneralError::ParseError("Acknowledgement".into()))?,
47        ))
48    }
49}
50
51impl BytesRepresentable for Acknowledgement {
52    const SIZE: usize = HalfKey::SIZE + OffchainSignature::SIZE;
53}
54
55impl Acknowledgement {
56    /// Attempts to verify the acknowledgement given the `sender_node_key` that sent the acknowledgement.
57    pub fn verify(self, sender_node_key: &OffchainPublicKey) -> Result<VerifiedAcknowledgement> {
58        let signature = OffchainSignature::try_from(&self.0[HalfKey::SIZE..HalfKey::SIZE + OffchainSignature::SIZE])?;
59        if signature.verify_message(&self.0[0..HalfKey::SIZE], sender_node_key) {
60            Ok(VerifiedAcknowledgement {
61                ack_key_share: HalfKey::try_from(&self.0[0..HalfKey::SIZE])?,
62                signature,
63            })
64        } else {
65            Err(CoreTypesError::InvalidAcknowledgement)
66        }
67    }
68}
69
70/// Represents packet acknowledgement whose signature has been already verified.
71///
72/// This acknowledgement cannot be serialized.
73#[derive(Copy, Clone, Debug, PartialEq)]
74pub struct VerifiedAcknowledgement {
75    ack_key_share: HalfKey,
76    signature: OffchainSignature,
77}
78
79impl VerifiedAcknowledgement {
80    pub fn new(ack_key_share: HalfKey, node_keypair: &OffchainKeypair) -> Self {
81        let signature = OffchainSignature::sign_message(ack_key_share.as_ref(), node_keypair);
82        Self {
83            ack_key_share,
84            signature,
85        }
86    }
87
88    /// Generates random but still a valid acknowledgement.
89    pub fn random(offchain_keypair: &OffchainKeypair) -> Self {
90        Self::new(HalfKey::random(), offchain_keypair)
91    }
92
93    /// Downgrades this verified acknowledgement to an unverified serializable one.
94    pub fn leak(self) -> Acknowledgement {
95        let mut ret = [0u8; Acknowledgement::SIZE];
96        ret[0..HalfKey::SIZE].copy_from_slice(self.ack_key_share.as_ref());
97        ret[HalfKey::SIZE..HalfKey::SIZE + OffchainSignature::SIZE].copy_from_slice(self.signature.as_ref());
98        Acknowledgement(ret)
99    }
100
101    /// Gets the acknowledged key out of this acknowledgement.
102    ///
103    /// This is the remaining part of the solution of the `Ticket` challenge.
104    pub fn ack_key_share(&self) -> &HalfKey {
105        &self.ack_key_share
106    }
107}
108
109/// Contains either unacknowledged ticket if we're waiting for the acknowledgement as a relayer
110/// or information if we wait for the acknowledgement as a sender.
111#[derive(Clone, Debug, PartialEq, Eq)]
112#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
113pub enum PendingAcknowledgement {
114    /// We're waiting for acknowledgement as a sender
115    WaitingAsSender,
116    /// We're waiting for the acknowledgement as a relayer with a ticket
117    WaitingAsRelayer(Box<UnacknowledgedTicket>),
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn acknowledgement_should_verify() -> anyhow::Result<()> {
126        let kp = OffchainKeypair::random();
127        let v_ack_1 = VerifiedAcknowledgement::random(&kp);
128        let v_ack_2 = v_ack_1.leak().verify(kp.public())?;
129
130        assert_eq!(v_ack_1, v_ack_2);
131        Ok(())
132    }
133}