bitcoin_peers_connection/
peer.rs1use bitcoin::p2p::address::AddrV2;
4use bitcoin::p2p::ServiceFlags;
5use std::fmt;
6
7pub const MIN_PROTOCOL_VERSION: u32 = 70001;
9pub const ADDRV2_MIN_PROTOCOL_VERSION: u32 = 70016;
13pub const SENDHEADERS_MIN_PROTOCOL_VERSION: u32 = 70012;
17pub const WTXID_RELAY_MIN_PROTOCOL_VERSION: u32 = 70016;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub enum PeerServices {
25 Known(ServiceFlags),
27 Unknown,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub enum PeerProtocolVersion {
46 Known(u32),
48 Unknown,
50}
51
52impl PeerProtocolVersion {
53 pub fn unwrap_or(self, default: u32) -> u32 {
63 match self {
64 PeerProtocolVersion::Known(v) => v,
65 PeerProtocolVersion::Unknown => default,
66 }
67 }
68}
69
70impl fmt::Display for PeerProtocolVersion {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match self {
73 PeerProtocolVersion::Known(version) => write!(f, "Known({version})"),
74 PeerProtocolVersion::Unknown => write!(f, "Unknown"),
75 }
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
81pub struct Peer {
82 pub address: AddrV2,
84 pub port: u16,
86 pub services: PeerServices,
88 pub version: PeerProtocolVersion,
90}
91
92impl Peer {
93 pub fn new(address: AddrV2, port: u16) -> Self {
95 Peer {
96 address,
97 port,
98 services: PeerServices::Unknown,
99 version: PeerProtocolVersion::Unknown,
100 }
101 }
102
103 pub fn with_services(address: AddrV2, port: u16, services: ServiceFlags) -> Self {
105 Peer {
106 address,
107 port,
108 services: PeerServices::Known(services),
109 version: PeerProtocolVersion::Unknown,
110 }
111 }
112
113 pub fn has_service(&self, service: ServiceFlags) -> bool {
123 match self.services {
124 PeerServices::Known(flags) => flags.has(service),
125 PeerServices::Unknown => false,
126 }
127 }
128
129 pub fn with_known_services(&self, services: ServiceFlags) -> Self {
131 Peer {
132 address: self.address.clone(),
133 port: self.port,
134 services: PeerServices::Known(services),
135 version: self.version,
136 }
137 }
138
139 pub fn with_known_version(&self, version: u32) -> Self {
141 Peer {
142 address: self.address.clone(),
143 port: self.port,
144 services: self.services,
145 version: PeerProtocolVersion::Known(version),
146 }
147 }
148}
149
150impl fmt::Display for Peer {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 write!(
153 f,
154 "{:?}:{} ([peer] services: {}, version: {})",
155 self.address,
156 self.port,
157 match self.services {
158 PeerServices::Known(flags) => flags.to_string(),
159 PeerServices::Unknown => "unknown".to_string(),
160 },
161 match self.version {
162 PeerProtocolVersion::Known(v) => v.to_string(),
163 PeerProtocolVersion::Unknown => "unknown".to_string(),
164 }
165 )
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172 use std::net::Ipv4Addr;
173
174 #[test]
175 fn test_peer_with_services() {
176 let addr = AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1));
177 let port = 8333;
178 let services = ServiceFlags::NETWORK;
179
180 let peer = Peer::with_services(addr.clone(), port, services);
181
182 assert_eq!(peer.address, addr);
183 assert_eq!(peer.port, port);
184 assert_eq!(peer.services, PeerServices::Known(services));
185 assert_eq!(peer.version, PeerProtocolVersion::Unknown);
186 assert!(peer.has_service(ServiceFlags::NETWORK));
187 }
188
189 #[test]
190 fn test_peer_constructors_equivalence() {
191 let addr = AddrV2::Ipv4(Ipv4Addr::new(192, 168, 1, 1));
192 let port = 8333;
193 let services = ServiceFlags::NETWORK | ServiceFlags::WITNESS;
194
195 let peer1 = Peer::with_services(addr.clone(), port, services);
197 let peer2 = Peer::new(addr.clone(), port).with_known_services(services);
198
199 assert_eq!(peer1, peer2);
200 }
201}