snarkos_node_network/
peer.rs1use crate::NodeType;
17use snarkvm::prelude::{Address, Network};
18use tracing::*;
19
20use std::{net::SocketAddr, time::Instant};
21
22#[derive(Clone, Debug)]
24pub enum Peer<N: Network> {
25 Candidate(CandidatePeer),
27 Connecting(ConnectingPeer),
29 Connected(ConnectedPeer<N>),
31}
32
33#[derive(Clone, Debug)]
35pub struct ConnectingPeer {
36 pub listener_addr: SocketAddr,
38 pub trusted: bool,
40}
41
42#[derive(Clone, Debug)]
44pub struct CandidatePeer {
45 pub listener_addr: SocketAddr,
47 pub trusted: bool,
49 pub last_height_seen: Option<u32>,
51 pub last_connection_attempt: Option<Instant>,
54 pub total_connection_attempts: u32,
56}
57
58#[derive(Clone, Debug)]
60pub struct ConnectedPeer<N: Network> {
61 pub listener_addr: SocketAddr,
63 pub connected_addr: SocketAddr,
65 pub connection_mode: ConnectionMode,
67 pub trusted: bool,
69 pub aleo_addr: Address<N>,
71 pub node_type: NodeType,
73 pub version: u32,
75 pub snarkos_sha: Option<[u8; 40]>,
77 pub last_height_seen: Option<u32>,
79 pub first_seen: Instant,
81 pub last_seen: Instant,
83}
84
85#[derive(Clone, Copy, Debug, PartialEq, Eq)]
87pub enum ConnectionMode {
88 Gateway,
89 Router,
90}
91
92impl<N: Network> Peer<N> {
93 pub const fn new_candidate(listener_addr: SocketAddr, trusted: bool) -> Self {
95 Self::Candidate(CandidatePeer {
96 listener_addr,
97 trusted,
98 last_height_seen: None,
99 last_connection_attempt: None,
100 total_connection_attempts: 0,
101 })
102 }
103
104 pub const fn new_connecting(listener_addr: SocketAddr, trusted: bool) -> Self {
106 Self::Connecting(ConnectingPeer { listener_addr, trusted })
107 }
108
109 #[allow(clippy::too_many_arguments)]
111 pub fn upgrade_to_connected(
112 &mut self,
113 connected_addr: SocketAddr,
114 listener_port: u16,
115 aleo_address: Address<N>,
116 node_type: NodeType,
117 node_version: u32,
118 snarkos_sha: Option<[u8; 40]>,
119 connection_mode: ConnectionMode,
120 ) {
121 let timestamp = Instant::now();
122 let listener_addr = SocketAddr::from((connected_addr.ip(), listener_port));
123
124 if !matches!(self, Self::Connecting(_)) {
127 warn!("Peer '{listener_addr}' is being upgraded to Connected, but isn't Connecting");
128 }
129
130 *self = Self::Connected(ConnectedPeer {
131 listener_addr,
132 connected_addr,
133 connection_mode,
134 aleo_addr: aleo_address,
135 node_type,
136 trusted: self.is_trusted(),
137 version: node_version,
138 snarkos_sha,
139 last_height_seen: None,
140 first_seen: timestamp,
141 last_seen: timestamp,
142 });
143 }
144
145 pub fn downgrade_to_candidate(&mut self, listener_addr: SocketAddr) {
147 *self = Self::Candidate(CandidatePeer {
148 listener_addr,
149 trusted: self.is_trusted(),
150 last_height_seen: self.last_height_seen(),
151 last_connection_attempt: None,
152 total_connection_attempts: 0,
153 });
154 }
155
156 pub fn node_type(&self) -> Option<NodeType> {
158 match self {
159 Self::Candidate(_) => None,
160 Self::Connecting(_) => None,
161 Self::Connected(peer) => Some(peer.node_type),
162 }
163 }
164
165 pub fn listener_addr(&self) -> SocketAddr {
167 match self {
168 Self::Candidate(p) => p.listener_addr,
169 Self::Connecting(p) => p.listener_addr,
170 Self::Connected(p) => p.listener_addr,
171 }
172 }
173
174 pub fn last_height_seen(&self) -> Option<u32> {
176 match self {
177 Self::Candidate(_) => None,
178 Self::Connecting(_) => None,
179 Self::Connected(peer) => peer.last_height_seen,
180 }
181 }
182
183 pub fn is_candidate(&self) -> bool {
185 matches!(self, Peer::Candidate(_))
186 }
187
188 pub fn is_connecting(&self) -> bool {
190 matches!(self, Peer::Connecting(_))
191 }
192
193 pub fn is_connected(&self) -> bool {
195 matches!(self, Peer::Connected(_))
196 }
197
198 pub fn is_trusted(&self) -> bool {
200 match self {
201 Self::Candidate(peer) => peer.trusted,
202 Self::Connecting(peer) => peer.trusted,
203 Self::Connected(peer) => peer.trusted,
204 }
205 }
206
207 pub fn update_last_seen(&mut self) {
209 if let Self::Connected(ConnectedPeer { last_seen, .. }) = self {
210 *last_seen = Instant::now();
211 }
212 }
213}