cuprate_p2p_core/
protocol.rs

1//! This module defines [`PeerRequest`] and [`PeerResponse`]. Cuprate's P2P crates works by translating network messages into an internal
2//! request/response enums, this is easy for levin "requests" and "responses" (admin messages) but takes a bit more work with "notifications"
3//! (protocol messages).
4//!
5//! Some notifications are easy to translate, like [`GetObjectsRequest`] is obviously a request but others like [`NewFluffyBlock`] are a
6//! bit tricker. To translate a [`NewFluffyBlock`] into a request/ response we will have to look to see if we asked for [`FluffyMissingTransactionsRequest`],
7//! if we have, we interpret [`NewFluffyBlock`] as a response, if not, it's a request that doesn't require a response.
8//!
9//! Here is every P2P request/response.
10//!
11//! *note admin messages are already request/response so "Handshake" is actually made of a `HandshakeRequest` & `HandshakeResponse`
12//!
13//! ```md
14//! Admin:
15//!     Handshake,
16//!     TimedSync,
17//!     Ping,
18//!     SupportFlags
19//! Protocol:
20//!     Request: GetObjectsRequest,                 Response: GetObjectsResponse,
21//!     Request: ChainRequest,                      Response: ChainResponse,
22//!     Request: FluffyMissingTransactionsRequest,  Response: NewFluffyBlock,  <- these 2 could be requests or responses
23//!     Request: GetTxPoolCompliment,               Response: NewTransactions, <-
24//!     Request: NewBlock,                          Response: None,
25//!     Request: NewFluffyBlock,                    Response: None,
26//!     Request: NewTransactions,                   Response: None
27//!```
28//!
29use cuprate_wire::{
30    protocol::{
31        ChainRequest, ChainResponse, FluffyMissingTransactionsRequest, GetObjectsRequest,
32        GetObjectsResponse, GetTxPoolCompliment, NewBlock, NewFluffyBlock, NewTransactions,
33    },
34    AdminRequestMessage, AdminResponseMessage,
35};
36
37mod try_from;
38
39/// An enum representing a request/ response combination, so a handshake request
40/// and response would have the same [`MessageID`]. This allows associating the
41/// correct response to a request.
42#[derive(Debug, Eq, PartialEq, Copy, Clone)]
43pub enum MessageID {
44    Handshake,
45    TimedSync,
46    Ping,
47    SupportFlags,
48
49    GetObjects,
50    GetChain,
51    FluffyMissingTxs,
52    GetTxPoolCompliment,
53    NewBlock,
54    NewFluffyBlock,
55    NewTransactions,
56}
57
58pub enum BroadcastMessage {
59    NewFluffyBlock(NewFluffyBlock),
60    NewTransactions(NewTransactions),
61}
62
63#[derive(Debug, Clone)]
64pub enum ProtocolRequest {
65    GetObjects(GetObjectsRequest),
66    GetChain(ChainRequest),
67    FluffyMissingTxs(FluffyMissingTransactionsRequest),
68    GetTxPoolCompliment(GetTxPoolCompliment),
69    NewBlock(NewBlock),
70    NewFluffyBlock(NewFluffyBlock),
71    NewTransactions(NewTransactions),
72}
73
74#[derive(Debug, Clone)]
75pub enum PeerRequest {
76    Admin(AdminRequestMessage),
77    Protocol(ProtocolRequest),
78}
79
80impl PeerRequest {
81    pub const fn id(&self) -> MessageID {
82        match self {
83            Self::Admin(admin_req) => match admin_req {
84                AdminRequestMessage::Handshake(_) => MessageID::Handshake,
85                AdminRequestMessage::TimedSync(_) => MessageID::TimedSync,
86                AdminRequestMessage::Ping => MessageID::Ping,
87                AdminRequestMessage::SupportFlags => MessageID::SupportFlags,
88            },
89            Self::Protocol(protocol_request) => match protocol_request {
90                ProtocolRequest::GetObjects(_) => MessageID::GetObjects,
91                ProtocolRequest::GetChain(_) => MessageID::GetChain,
92                ProtocolRequest::FluffyMissingTxs(_) => MessageID::FluffyMissingTxs,
93                ProtocolRequest::GetTxPoolCompliment(_) => MessageID::GetTxPoolCompliment,
94                ProtocolRequest::NewBlock(_) => MessageID::NewBlock,
95                ProtocolRequest::NewFluffyBlock(_) => MessageID::NewFluffyBlock,
96                ProtocolRequest::NewTransactions(_) => MessageID::NewTransactions,
97            },
98        }
99    }
100
101    pub const fn needs_response(&self) -> bool {
102        !matches!(
103            self,
104            Self::Protocol(
105                ProtocolRequest::NewBlock(_)
106                    | ProtocolRequest::NewFluffyBlock(_)
107                    | ProtocolRequest::NewTransactions(_)
108            )
109        )
110    }
111}
112
113#[derive(Debug, Clone)]
114pub enum ProtocolResponse {
115    GetObjects(GetObjectsResponse),
116    GetChain(ChainResponse),
117    NewFluffyBlock(NewFluffyBlock),
118    NewTransactions(NewTransactions),
119    FluffyMissingTransactionsRequest(FluffyMissingTransactionsRequest),
120    NA,
121}
122
123#[derive(Debug, Clone)]
124pub enum PeerResponse {
125    Admin(AdminResponseMessage),
126    Protocol(ProtocolResponse),
127}
128
129impl PeerResponse {
130    pub const fn id(&self) -> Option<MessageID> {
131        Some(match self {
132            Self::Admin(admin_res) => match admin_res {
133                AdminResponseMessage::Handshake(_) => MessageID::Handshake,
134                AdminResponseMessage::TimedSync(_) => MessageID::TimedSync,
135                AdminResponseMessage::Ping(_) => MessageID::Ping,
136                AdminResponseMessage::SupportFlags(_) => MessageID::SupportFlags,
137            },
138            Self::Protocol(protocol_res) => match protocol_res {
139                ProtocolResponse::GetObjects(_) => MessageID::GetObjects,
140                ProtocolResponse::GetChain(_) => MessageID::GetChain,
141                ProtocolResponse::NewFluffyBlock(_) => MessageID::NewBlock,
142                ProtocolResponse::NewTransactions(_) => MessageID::NewFluffyBlock,
143                ProtocolResponse::FluffyMissingTransactionsRequest(_) => {
144                    MessageID::FluffyMissingTxs
145                }
146
147                ProtocolResponse::NA => return None,
148            },
149        })
150    }
151}