Skip to main content

reth_eth_wire/
protocol.rs

1//! A Protocol defines a P2P subprotocol in an `RLPx` connection
2
3use crate::{Capability, EthMessageID, EthVersion, SnapVersion};
4
5/// Type that represents a [Capability] and the number of messages it uses.
6///
7/// Only the [Capability] is shared with the remote peer, assuming both parties know the number of
8/// messages used by the protocol which is used for message ID multiplexing.
9#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Protocol {
12    /// The name of the subprotocol
13    pub cap: Capability,
14    /// The number of messages used/reserved by this protocol
15    ///
16    /// This is used for message ID multiplexing
17    messages: u8,
18}
19
20impl Protocol {
21    /// Create a new protocol with the given name and number of messages
22    pub const fn new(cap: Capability, messages: u8) -> Self {
23        Self { cap, messages }
24    }
25
26    /// Returns the corresponding eth capability for the given version.
27    pub const fn eth(version: EthVersion) -> Self {
28        let cap = Capability::eth(version);
29        let messages = EthMessageID::message_count(version);
30        Self::new(cap, messages)
31    }
32
33    /// Returns the corresponding snap capability for the given version.
34    pub const fn snap(version: SnapVersion) -> Self {
35        let cap = Capability::snap(version);
36        let messages = version.message_count();
37        Self::new(cap, messages)
38    }
39
40    /// Returns the [`EthVersion::Eth66`] capability.
41    pub const fn eth_66() -> Self {
42        Self::eth(EthVersion::Eth66)
43    }
44
45    /// Returns the [`EthVersion::Eth67`] capability.
46    pub const fn eth_67() -> Self {
47        Self::eth(EthVersion::Eth67)
48    }
49
50    /// Returns the [`EthVersion::Eth68`] capability.
51    pub const fn eth_68() -> Self {
52        Self::eth(EthVersion::Eth68)
53    }
54
55    /// Returns the `snap/1` capability.
56    pub const fn snap_1() -> Self {
57        Self::snap(SnapVersion::V1)
58    }
59
60    /// Returns the `snap/2` capability.
61    pub const fn snap_2() -> Self {
62        Self::snap(SnapVersion::V2)
63    }
64
65    /// Consumes the type and returns a tuple of the [Capability] and number of messages.
66    #[inline]
67    pub(crate) fn split(self) -> (Capability, u8) {
68        (self.cap, self.messages)
69    }
70
71    /// The number of values needed to represent all message IDs of capability.
72    pub const fn messages(&self) -> u8 {
73        self.messages
74    }
75}
76
77impl From<EthVersion> for Protocol {
78    fn from(version: EthVersion) -> Self {
79        Self::eth(version)
80    }
81}
82
83/// A helper type to keep track of the protocol version and number of messages used by the protocol.
84#[derive(Clone, Debug, PartialEq, Eq, Hash)]
85pub(crate) struct ProtoVersion {
86    /// Number of messages for a protocol
87    pub(crate) messages: u8,
88    /// Version of the protocol
89    pub(crate) version: usize,
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_protocol_eth_message_count() {
98        // Test that Protocol::eth() returns correct message counts for each version
99        // This ensures that EthMessageID::message_count() produces the expected results
100        assert_eq!(Protocol::eth(EthVersion::Eth66).messages(), 17);
101        assert_eq!(Protocol::eth(EthVersion::Eth67).messages(), 17);
102        assert_eq!(Protocol::eth(EthVersion::Eth68).messages(), 17);
103        assert_eq!(Protocol::eth(EthVersion::Eth69).messages(), 18);
104        assert_eq!(Protocol::eth(EthVersion::Eth70).messages(), 18);
105        assert_eq!(Protocol::eth(EthVersion::Eth71).messages(), 20);
106        assert_eq!(Protocol::snap(SnapVersion::V1).messages(), 8);
107        assert_eq!(Protocol::snap(SnapVersion::V2).messages(), 10);
108    }
109}