Skip to main content

hotshot_types/traits/
network.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7//! Network access compatibility
8//!
9//! Contains types and traits used by `HotShot` to abstract over network access
10
11use std::hash::Hash;
12
13use serde::{Deserialize, Serialize};
14use thiserror::Error;
15
16use super::{node_implementation::NodeType, signature_key::SignatureKey};
17use crate::{data::ViewNumber, message::SequencingMessage};
18
19/// Errors that can occur in the network
20#[derive(Debug, Error)]
21pub enum NetworkError {
22    /// Multiple errors. Allows us to roll up multiple errors into one.
23    #[error("Multiple errors: {0:?}")]
24    Multiple(Vec<NetworkError>),
25
26    /// A configuration error
27    #[error("Configuration error: {0}")]
28    ConfigError(String),
29
30    /// An error occurred while sending a message
31    #[error("Failed to send message: {0}")]
32    MessageSendError(String),
33
34    /// An error occurred while receiving a message
35    #[error("Failed to receive message: {0}")]
36    MessageReceiveError(String),
37
38    /// The feature is unimplemented
39    #[error("Unimplemented")]
40    Unimplemented,
41
42    /// An error occurred while attempting to listen
43    #[error("Listen error: {0}")]
44    ListenError(String),
45
46    /// Failed to send over a channel
47    #[error("Channel send error: {0}")]
48    ChannelSendError(String),
49
50    /// Failed to receive over a channel
51    #[error("Channel receive error: {0}")]
52    ChannelReceiveError(String),
53
54    /// The network has been shut down and can no longer be used
55    #[error("Network has been shut down")]
56    ShutDown,
57
58    /// Failed to serialize
59    #[error("Failed to serialize: {0}")]
60    FailedToSerialize(String),
61
62    /// Failed to deserialize
63    #[error("Failed to deserialize: {0}")]
64    FailedToDeserialize(String),
65
66    /// Timed out performing an operation
67    #[error("Timeout: {0}")]
68    Timeout(String),
69
70    /// The network request had been cancelled before it could be fulfilled
71    #[error("The request was cancelled before it could be fulfilled")]
72    RequestCancelled,
73
74    /// This node does not have any peers yet
75    #[error("This node does not have any peers yet")]
76    NoPeersYet,
77
78    /// Failed to look up a node on the network
79    #[error("Node lookup failed: {0}")]
80    LookupError(String),
81}
82
83/// Trait that bundles what we need from a request ID
84pub trait Id: Eq + PartialEq + Hash {}
85
86/// a message
87pub trait ViewMessage<TYPES: NodeType> {
88    /// get the view out of the message
89    fn view_number(&self) -> ViewNumber;
90}
91
92/// A request for some data that the consensus layer is asking for.
93#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
94#[serde(bound(deserialize = ""))]
95pub struct DataRequest<TYPES: NodeType> {
96    /// Request
97    pub request: RequestKind<TYPES>,
98    /// View this message is for
99    pub view: ViewNumber,
100    /// signature of the Sha256 hash of the data so outsiders can't use know
101    /// public keys with stake.
102    pub signature: <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
103}
104
105/// Underlying data request
106#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
107pub enum RequestKind<TYPES: NodeType> {
108    /// Request VID data by our key and the VID commitment
109    Vid(ViewNumber, TYPES::SignatureKey),
110    /// Request a DA proposal for a certain view
111    DaProposal(ViewNumber),
112    /// Request for quorum proposal for a view
113    Proposal(ViewNumber),
114}
115
116impl<TYPES: NodeType> std::fmt::Debug for RequestKind<TYPES> {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        match self {
119            RequestKind::Vid(view, key) => write!(f, "Vid({view:?}, {key})"),
120            RequestKind::DaProposal(view) => write!(f, "DaProposal({view:?})"),
121            RequestKind::Proposal(view) => write!(f, "Proposal({view:?})"),
122        }
123    }
124}
125
126/// A response for a request.  `SequencingMessage` is the same as other network messages
127/// The kind of message `M` is determined by what we requested
128#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
129#[serde(bound(deserialize = ""))]
130#[allow(clippy::large_enum_variant)]
131/// TODO: Put `Found` content in a `Box` to make enum smaller
132pub enum ResponseMessage<TYPES: NodeType> {
133    /// Peer returned us some data
134    Found(SequencingMessage<TYPES>),
135    /// Peer failed to get us data
136    NotFound,
137    /// The Request was denied
138    Denied,
139}
140
141/// Changes that can occur in the network
142#[derive(Debug)]
143pub enum NetworkChange<P: SignatureKey> {
144    /// A node is connected
145    NodeConnected(P),
146
147    /// A node is disconnected
148    NodeDisconnected(P),
149}