reth_ress_protocol/types.rs
1use alloy_primitives::bytes::{Buf, BufMut};
2use alloy_rlp::{Decodable, Encodable};
3
4/// Represents the type of node in the RESS protocol.
5///
6/// This enum is used during the handshake phase to identify whether a peer is a stateless
7/// or stateful node. The node type determines which connections are valid:
8/// - Stateless ↔ Stateless: valid
9/// - Stateless ↔ Stateful: valid
10/// - Stateful ↔ Stateful: invalid
11///
12/// Use [`is_valid_connection`](Self::is_valid_connection) to check if a connection between
13/// two node types is allowed.
14#[repr(u8)]
15#[derive(PartialEq, Eq, Copy, Clone, Debug)]
16#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
17pub enum NodeType {
18 /// Stateless ress node.
19 Stateless = 0x00,
20 /// Stateful reth node.
21 Stateful,
22}
23
24impl Encodable for NodeType {
25 fn encode(&self, out: &mut dyn BufMut) {
26 out.put_u8(*self as u8);
27 }
28
29 fn length(&self) -> usize {
30 1
31 }
32}
33
34impl Decodable for NodeType {
35 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
36 let id = match buf.first().ok_or(alloy_rlp::Error::InputTooShort)? {
37 0x00 => Self::Stateless,
38 0x01 => Self::Stateful,
39 _ => return Err(alloy_rlp::Error::Custom("Invalid message type")),
40 };
41 buf.advance(1);
42 Ok(id)
43 }
44}
45
46impl NodeType {
47 /// Return `true` if node type is stateful.
48 pub const fn is_stateful(&self) -> bool {
49 matches!(self, Self::Stateful)
50 }
51
52 /// Return `true` if the connection between this and other node types
53 /// can be considered valid.
54 ///
55 /// Validity:
56 /// | stateless | stateful |
57 /// ----------|-----------|----------|
58 /// stateless | + | + |
59 /// stateful | + | - |
60 pub const fn is_valid_connection(&self, other: &Self) -> bool {
61 !self.is_stateful() || !other.is_stateful()
62 }
63}