1#[cfg(feature = "std")]
9pub mod address;
10#[cfg(feature = "std")]
11pub mod message;
12#[cfg(feature = "std")]
13pub mod message_blockdata;
14#[cfg(feature = "std")]
15pub mod message_bloom;
16#[cfg(feature = "std")]
17pub mod message_compact_blocks;
18#[cfg(feature = "std")]
19pub mod message_filter;
20#[cfg(feature = "std")]
21pub mod message_network;
22
23use core::str::FromStr;
24use core::{fmt, ops};
25
26use hex::FromHex;
27use internals::{debug_from_display, write_err};
28use io::{Read, Write};
29
30use crate::consensus::encode::{self, Decodable, Encodable};
31use crate::consensus::Params;
32use crate::network::Network;
33use crate::prelude::*;
34
35#[rustfmt::skip]
36#[doc(inline)]
37#[cfg(feature = "std")]
38pub use self::address::Address;
39
40pub const PROTOCOL_VERSION: u32 = 70001;
58
59#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
61pub struct ServiceFlags(u64);
62
63impl ServiceFlags {
64 pub const NONE: ServiceFlags = ServiceFlags(0);
66
67 pub const NETWORK: ServiceFlags = ServiceFlags(1 << 0);
71
72 pub const GETUTXO: ServiceFlags = ServiceFlags(1 << 1);
76
77 pub const BLOOM: ServiceFlags = ServiceFlags(1 << 2);
81
82 pub const WITNESS: ServiceFlags = ServiceFlags(1 << 3);
85
86 pub const COMPACT_FILTERS: ServiceFlags = ServiceFlags(1 << 6);
89
90 pub const NETWORK_LIMITED: ServiceFlags = ServiceFlags(1 << 10);
94
95 pub const P2P_V2: ServiceFlags = ServiceFlags(1 << 11);
98
99 pub fn add(&mut self, other: ServiceFlags) -> ServiceFlags {
105 self.0 |= other.0;
106 *self
107 }
108
109 pub fn remove(&mut self, other: ServiceFlags) -> ServiceFlags {
113 self.0 ^= other.0;
114 *self
115 }
116
117 pub fn has(self, flags: ServiceFlags) -> bool { (self.0 | flags.0) == self.0 }
119
120 pub fn to_u64(self) -> u64 { self.0 }
122}
123
124impl fmt::LowerHex for ServiceFlags {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
126}
127
128impl fmt::UpperHex for ServiceFlags {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
130}
131
132impl fmt::Display for ServiceFlags {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 let mut flags = *self;
135 if flags == ServiceFlags::NONE {
136 return write!(f, "ServiceFlags(NONE)");
137 }
138 let mut first = true;
139 macro_rules! write_flag {
140 ($f:ident) => {
141 if flags.has(ServiceFlags::$f) {
142 if !first {
143 write!(f, "|")?;
144 }
145 first = false;
146 write!(f, stringify!($f))?;
147 flags.remove(ServiceFlags::$f);
148 }
149 };
150 }
151 write!(f, "ServiceFlags(")?;
152 write_flag!(NETWORK);
153 write_flag!(GETUTXO);
154 write_flag!(BLOOM);
155 write_flag!(WITNESS);
156 write_flag!(COMPACT_FILTERS);
157 write_flag!(NETWORK_LIMITED);
158 write_flag!(P2P_V2);
159 if flags != ServiceFlags::NONE {
161 if !first {
162 write!(f, "|")?;
163 }
164 write!(f, "0x{:x}", flags)?;
165 }
166 write!(f, ")")
167 }
168}
169
170impl From<u64> for ServiceFlags {
171 fn from(f: u64) -> Self { ServiceFlags(f) }
172}
173
174impl From<ServiceFlags> for u64 {
175 fn from(flags: ServiceFlags) -> Self { flags.0 }
176}
177
178impl ops::BitOr for ServiceFlags {
179 type Output = Self;
180
181 fn bitor(mut self, rhs: Self) -> Self { self.add(rhs) }
182}
183
184impl ops::BitOrAssign for ServiceFlags {
185 fn bitor_assign(&mut self, rhs: Self) { self.add(rhs); }
186}
187
188impl ops::BitXor for ServiceFlags {
189 type Output = Self;
190
191 fn bitxor(mut self, rhs: Self) -> Self { self.remove(rhs) }
192}
193
194impl ops::BitXorAssign for ServiceFlags {
195 fn bitxor_assign(&mut self, rhs: Self) { self.remove(rhs); }
196}
197
198impl Encodable for ServiceFlags {
199 #[inline]
200 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
201 self.0.consensus_encode(w)
202 }
203}
204
205impl Decodable for ServiceFlags {
206 #[inline]
207 fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
208 Ok(ServiceFlags(Decodable::consensus_decode(r)?))
209 }
210}
211#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
213pub struct Magic([u8; 4]);
214
215impl Magic {
216 pub const BITCOIN: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]);
218 #[deprecated(since = "0.32.4", note = "Use TESTNET3 instead")]
220 pub const TESTNET: Self = Self([0x0B, 0x11, 0x09, 0x07]);
221 pub const TESTNET3: Self = Self([0x0B, 0x11, 0x09, 0x07]);
223 pub const TESTNET4: Self = Self([0x1c, 0x16, 0x3f, 0x28]);
225 pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]);
227 pub const REGTEST: Self = Self([0xFA, 0xBF, 0xB5, 0xDA]);
229
230 pub fn from_bytes(bytes: [u8; 4]) -> Magic { Magic(bytes) }
232
233 pub fn to_bytes(self) -> [u8; 4] { self.0 }
235
236 pub fn from_params(params: impl AsRef<Params>) -> Self { params.as_ref().network.into() }
238}
239
240impl FromStr for Magic {
241 type Err = ParseMagicError;
242
243 fn from_str(s: &str) -> Result<Magic, Self::Err> {
244 match <[u8; 4]>::from_hex(s) {
245 Ok(magic) => Ok(Magic::from_bytes(magic)),
246 Err(e) => Err(ParseMagicError { error: e, magic: s.to_owned() }),
247 }
248 }
249}
250
251impl From<Network> for Magic {
252 fn from(network: Network) -> Magic {
253 match network {
254 Network::Bitcoin => Magic::BITCOIN,
256 Network::Testnet => Magic::TESTNET3,
257 Network::Testnet4 => Magic::TESTNET4,
258 Network::Signet => Magic::SIGNET,
259 Network::Regtest => Magic::REGTEST,
260 }
261 }
262}
263
264impl TryFrom<Magic> for Network {
265 type Error = UnknownMagicError;
266
267 fn try_from(magic: Magic) -> Result<Self, Self::Error> {
268 match magic {
269 Magic::BITCOIN => Ok(Network::Bitcoin),
271 Magic::TESTNET3 => Ok(Network::Testnet),
272 Magic::TESTNET4 => Ok(Network::Testnet4),
273 Magic::SIGNET => Ok(Network::Signet),
274 Magic::REGTEST => Ok(Network::Regtest),
275 _ => Err(UnknownMagicError(magic)),
276 }
277 }
278}
279
280impl fmt::Display for Magic {
281 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
282 hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?;
283 Ok(())
284 }
285}
286debug_from_display!(Magic);
287
288impl fmt::LowerHex for Magic {
289 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
290 hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?;
291 Ok(())
292 }
293}
294
295impl fmt::UpperHex for Magic {
296 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
297 hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Upper)?;
298 Ok(())
299 }
300}
301
302impl Encodable for Magic {
303 fn consensus_encode<W: Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
304 self.0.consensus_encode(writer)
305 }
306}
307
308impl Decodable for Magic {
309 fn consensus_decode<R: Read + ?Sized>(reader: &mut R) -> Result<Self, encode::Error> {
310 Ok(Magic(Decodable::consensus_decode(reader)?))
311 }
312}
313
314impl AsRef<[u8]> for Magic {
315 fn as_ref(&self) -> &[u8] { &self.0 }
316}
317
318impl AsRef<[u8; 4]> for Magic {
319 fn as_ref(&self) -> &[u8; 4] { &self.0 }
320}
321
322impl AsMut<[u8]> for Magic {
323 fn as_mut(&mut self) -> &mut [u8] { &mut self.0 }
324}
325
326impl AsMut<[u8; 4]> for Magic {
327 fn as_mut(&mut self) -> &mut [u8; 4] { &mut self.0 }
328}
329
330impl Borrow<[u8]> for Magic {
331 fn borrow(&self) -> &[u8] { &self.0 }
332}
333
334impl Borrow<[u8; 4]> for Magic {
335 fn borrow(&self) -> &[u8; 4] { &self.0 }
336}
337
338impl BorrowMut<[u8]> for Magic {
339 fn borrow_mut(&mut self) -> &mut [u8] { &mut self.0 }
340}
341
342impl BorrowMut<[u8; 4]> for Magic {
343 fn borrow_mut(&mut self) -> &mut [u8; 4] { &mut self.0 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq)]
348#[non_exhaustive]
349pub struct ParseMagicError {
350 error: hex::HexToArrayError,
352 magic: String,
354}
355
356impl fmt::Display for ParseMagicError {
357 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
358 write_err!(f, "failed to parse {} as network magic", self.magic; self.error)
359 }
360}
361
362#[cfg(feature = "std")]
363impl std::error::Error for ParseMagicError {
364 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) }
365}
366
367#[derive(Debug, Clone, PartialEq, Eq)]
369#[non_exhaustive]
370pub struct UnknownMagicError(Magic);
371
372impl fmt::Display for UnknownMagicError {
373 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
374 write!(f, "unknown network magic {}", self.0)
375 }
376}
377
378#[cfg(feature = "std")]
379impl std::error::Error for UnknownMagicError {
380 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
381}
382
383#[cfg(test)]
384mod tests {
385 use super::*;
386
387 #[test]
388 fn service_flags_test() {
389 let all = [
390 ServiceFlags::NETWORK,
391 ServiceFlags::GETUTXO,
392 ServiceFlags::BLOOM,
393 ServiceFlags::WITNESS,
394 ServiceFlags::COMPACT_FILTERS,
395 ServiceFlags::NETWORK_LIMITED,
396 ];
397
398 let mut flags = ServiceFlags::NONE;
399 for f in all.iter() {
400 assert!(!flags.has(*f));
401 }
402
403 flags |= ServiceFlags::WITNESS;
404 assert_eq!(flags, ServiceFlags::WITNESS);
405
406 let mut flags2 = flags | ServiceFlags::GETUTXO;
407 for f in all.iter() {
408 assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO);
409 }
410
411 flags2 ^= ServiceFlags::WITNESS;
412 assert_eq!(flags2, ServiceFlags::GETUTXO);
413
414 flags2 |= ServiceFlags::COMPACT_FILTERS;
415 flags2 ^= ServiceFlags::GETUTXO;
416 assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS);
417
418 assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string());
420 assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string());
421 let flag = ServiceFlags::WITNESS | ServiceFlags::BLOOM | ServiceFlags::NETWORK;
422 assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flag.to_string());
423 let flag = ServiceFlags::WITNESS | 0xf0.into();
424 assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
425 }
426
427 #[test]
428 fn magic_from_str() {
429 let known_network_magic_strs = [
430 ("f9beb4d9", Network::Bitcoin),
431 ("0b110907", Network::Testnet),
432 ("1c163f28", Network::Testnet4),
433 ("fabfb5da", Network::Regtest),
434 ("0a03cf40", Network::Signet),
435 ];
436
437 for (magic_str, network) in &known_network_magic_strs {
438 let magic: Magic = Magic::from_str(magic_str).unwrap();
439 assert_eq!(Network::try_from(magic).unwrap(), *network);
440 assert_eq!(&magic.to_string(), magic_str);
441 }
442 }
443}