cuprate/p2p/p2p-core/src/protocol.rs
hinto-janai 848a6a71c4
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
p2p/p2p-core: enable workspace lints (#288)
* p2p-core: enable workspace lints

* fmt

* fix tests

* fixes

* fixes

* fixes

* expect reason
2024-09-21 01:37:06 +01:00

147 lines
5.4 KiB
Rust

//! This module defines [`PeerRequest`] and [`PeerResponse`]. Cuprate's P2P crates works by translating network messages into an internal
//! request/response enums, this is easy for levin "requests" and "responses" (admin messages) but takes a bit more work with "notifications"
//! (protocol messages).
//!
//! Some notifications are easy to translate, like [`GetObjectsRequest`] is obviously a request but others like [`NewFluffyBlock`] are a
//! bit tricker. To translate a [`NewFluffyBlock`] into a request/ response we will have to look to see if we asked for [`FluffyMissingTransactionsRequest`],
//! if we have, we interpret [`NewFluffyBlock`] as a response, if not, it's a request that doesn't require a response.
//!
//! Here is every P2P request/response.
//!
//! *note admin messages are already request/response so "Handshake" is actually made of a `HandshakeRequest` & `HandshakeResponse`
//!
//! ```md
//! Admin:
//! Handshake,
//! TimedSync,
//! Ping,
//! SupportFlags
//! Protocol:
//! Request: GetObjectsRequest, Response: GetObjectsResponse,
//! Request: ChainRequest, Response: ChainResponse,
//! Request: FluffyMissingTransactionsRequest, Response: NewFluffyBlock, <- these 2 could be requests or responses
//! Request: GetTxPoolCompliment, Response: NewTransactions, <-
//! Request: NewBlock, Response: None,
//! Request: NewFluffyBlock, Response: None,
//! Request: NewTransactions, Response: None
//!```
//!
use cuprate_wire::{
protocol::{
ChainRequest, ChainResponse, FluffyMissingTransactionsRequest, GetObjectsRequest,
GetObjectsResponse, GetTxPoolCompliment, NewBlock, NewFluffyBlock, NewTransactions,
},
AdminRequestMessage, AdminResponseMessage,
};
mod try_from;
/// An enum representing a request/ response combination, so a handshake request
/// and response would have the same [`MessageID`]. This allows associating the
/// correct response to a request.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum MessageID {
Handshake,
TimedSync,
Ping,
SupportFlags,
GetObjects,
GetChain,
FluffyMissingTxs,
GetTxPoolCompliment,
NewBlock,
NewFluffyBlock,
NewTransactions,
}
pub enum BroadcastMessage {
NewFluffyBlock(NewFluffyBlock),
NewTransaction(NewTransactions),
}
#[derive(Debug, Clone)]
pub enum ProtocolRequest {
GetObjects(GetObjectsRequest),
GetChain(ChainRequest),
FluffyMissingTxs(FluffyMissingTransactionsRequest),
GetTxPoolCompliment(GetTxPoolCompliment),
NewBlock(NewBlock),
NewFluffyBlock(NewFluffyBlock),
NewTransactions(NewTransactions),
}
#[derive(Debug, Clone)]
pub enum PeerRequest {
Admin(AdminRequestMessage),
Protocol(ProtocolRequest),
}
impl PeerRequest {
pub const fn id(&self) -> MessageID {
match self {
Self::Admin(admin_req) => match admin_req {
AdminRequestMessage::Handshake(_) => MessageID::Handshake,
AdminRequestMessage::TimedSync(_) => MessageID::TimedSync,
AdminRequestMessage::Ping => MessageID::Ping,
AdminRequestMessage::SupportFlags => MessageID::SupportFlags,
},
Self::Protocol(protocol_request) => match protocol_request {
ProtocolRequest::GetObjects(_) => MessageID::GetObjects,
ProtocolRequest::GetChain(_) => MessageID::GetChain,
ProtocolRequest::FluffyMissingTxs(_) => MessageID::FluffyMissingTxs,
ProtocolRequest::GetTxPoolCompliment(_) => MessageID::GetTxPoolCompliment,
ProtocolRequest::NewBlock(_) => MessageID::NewBlock,
ProtocolRequest::NewFluffyBlock(_) => MessageID::NewFluffyBlock,
ProtocolRequest::NewTransactions(_) => MessageID::NewTransactions,
},
}
}
pub const fn needs_response(&self) -> bool {
!matches!(
self,
Self::Protocol(
ProtocolRequest::NewBlock(_)
| ProtocolRequest::NewFluffyBlock(_)
| ProtocolRequest::NewTransactions(_)
)
)
}
}
#[derive(Debug, Clone)]
pub enum ProtocolResponse {
GetObjects(GetObjectsResponse),
GetChain(ChainResponse),
NewFluffyBlock(NewFluffyBlock),
NewTransactions(NewTransactions),
NA,
}
#[derive(Debug, Clone)]
pub enum PeerResponse {
Admin(AdminResponseMessage),
Protocol(ProtocolResponse),
}
impl PeerResponse {
pub const fn id(&self) -> Option<MessageID> {
Some(match self {
Self::Admin(admin_res) => match admin_res {
AdminResponseMessage::Handshake(_) => MessageID::Handshake,
AdminResponseMessage::TimedSync(_) => MessageID::TimedSync,
AdminResponseMessage::Ping(_) => MessageID::Ping,
AdminResponseMessage::SupportFlags(_) => MessageID::SupportFlags,
},
Self::Protocol(protocol_res) => match protocol_res {
ProtocolResponse::GetObjects(_) => MessageID::GetObjects,
ProtocolResponse::GetChain(_) => MessageID::GetChain,
ProtocolResponse::NewFluffyBlock(_) => MessageID::NewBlock,
ProtocolResponse::NewTransactions(_) => MessageID::NewFluffyBlock,
ProtocolResponse::NA => return None,
},
})
}
}