sapio_bitcoin/network/
constants.rs

1// Rust Bitcoin Library
2// Written in 2014 by
3//   Andrew Poelstra <apoelstra@wpsoftware.net>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Bitcoin network constants.
16//!
17//! This module provides various constants relating to the Bitcoin network
18//! protocol, such as protocol versioning and magic header bytes.
19//!
20//! The [`Network`][1] type implements the [`Decodable`][2] and
21//! [`Encodable`][3] traits and encodes the magic bytes of the given
22//! network.
23//!
24//! [1]: enum.Network.html
25//! [2]: ../../consensus/encode/trait.Decodable.html
26//! [3]: ../../consensus/encode/trait.Encodable.html
27//!
28//! # Example: encoding a network's magic bytes
29//!
30//! ```rust
31//! use bitcoin::network::constants::Network;
32//! use bitcoin::consensus::encode::serialize;
33//!
34//! let network = Network::Bitcoin;
35//! let bytes = serialize(&network.magic());
36//!
37//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
38//! ```
39
40use core::{fmt, ops, convert::From};
41
42use io;
43use consensus::encode::{self, Encodable, Decodable};
44
45/// Version of the protocol as appearing in network message headers
46/// This constant is used to signal to other peers which features you support.
47/// Increasing it implies that your software also supports every feature prior to this version.
48/// Doing so without support may lead to you incorrectly banning other peers or other peers banning you.
49/// These are the features required for each version:
50/// 70016 - Support receiving `wtxidrelay` message between `version` and `verack` message
51/// 70015 - Support receiving invalid compact blocks from a peer without banning them
52/// 70014 - Support compact block messages `sendcmpct`, `cmpctblock`, `getblocktxn` and `blocktxn`
53/// 70013 - Support `feefilter` message
54/// 70012 - Support `sendheaders` message and announce new blocks via headers rather than inv
55/// 70011 - Support NODE_BLOOM service flag and don't support bloom filter messages if it is not set
56/// 70002 - Support `reject` message
57/// 70001 - Support bloom filter messages `filterload`, `filterclear` `filteradd`, `merkleblock` and FILTERED_BLOCK inventory type
58/// 60002 - Support `mempool` message
59/// 60001 - Support `pong` message and nonce in `ping` message
60pub const PROTOCOL_VERSION: u32 = 70001;
61
62user_enum! {
63    /// The cryptocurrency to act on
64    #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
65    pub enum Network {
66        /// Classic Bitcoin
67        Bitcoin <-> "bitcoin",
68        /// Bitcoin's testnet
69        Testnet <-> "testnet",
70        /// Bitcoin's signet
71        Signet <-> "signet",
72        /// Bitcoin's regtest
73        Regtest <-> "regtest"
74    }
75}
76
77impl Network {
78    /// Creates a `Network` from the magic bytes.
79    ///
80    /// # Examples
81    ///
82    /// ```rust
83    /// use bitcoin::network::constants::Network;
84    ///
85    /// assert_eq!(Some(Network::Bitcoin), Network::from_magic(0xD9B4BEF9));
86    /// assert_eq!(None, Network::from_magic(0xFFFFFFFF));
87    /// ```
88    pub fn from_magic(magic: u32) -> Option<Network> {
89        // Note: any new entries here must be added to `magic` below
90        match magic {
91            0xD9B4BEF9 => Some(Network::Bitcoin),
92            0x0709110B => Some(Network::Testnet),
93            0x40CF030A => Some(Network::Signet),
94            0xDAB5BFFA => Some(Network::Regtest),
95            _ => None
96        }
97    }
98
99    /// Return the network magic bytes, which should be encoded little-endian
100    /// at the start of every message
101    ///
102    /// # Examples
103    ///
104    /// ```rust
105    /// use bitcoin::network::constants::Network;
106    ///
107    /// let network = Network::Bitcoin;
108    /// assert_eq!(network.magic(), 0xD9B4BEF9);
109    /// ```
110    pub fn magic(self) -> u32 {
111        // Note: any new entries here must be added to `from_magic` above
112        match self {
113            Network::Bitcoin => 0xD9B4BEF9,
114            Network::Testnet => 0x0709110B,
115            Network::Signet  => 0x40CF030A,
116            Network::Regtest => 0xDAB5BFFA,
117        }
118    }
119}
120
121/// Flags to indicate which network services a node supports.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
123pub struct ServiceFlags(u64);
124
125impl ServiceFlags {
126    /// NONE means no services supported.
127    pub const NONE: ServiceFlags = ServiceFlags(0);
128
129    /// NETWORK means that the node is capable of serving the complete block chain. It is currently
130    /// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light
131    /// clients.
132    pub const NETWORK: ServiceFlags = ServiceFlags(1 << 0);
133
134    /// GETUTXO means the node is capable of responding to the getutxo protocol request.  Bitcoin
135    /// Core does not support this but a patch set called Bitcoin XT does.
136    /// See BIP 64 for details on how this is implemented.
137    pub const GETUTXO: ServiceFlags = ServiceFlags(1 << 1);
138
139    /// BLOOM means the node is capable and willing to handle bloom-filtered connections.  Bitcoin
140    /// Core nodes used to support this by default, without advertising this bit, but no longer do
141    /// as of protocol version 70011 (= NO_BLOOM_VERSION)
142    pub const BLOOM: ServiceFlags = ServiceFlags(1 << 2);
143
144    /// WITNESS indicates that a node can be asked for blocks and transactions including witness
145    /// data.
146    pub const WITNESS: ServiceFlags = ServiceFlags(1 << 3);
147
148    /// COMPACT_FILTERS means the node will service basic block filter requests.
149    /// See BIP157 and BIP158 for details on how this is implemented.
150    pub const COMPACT_FILTERS: ServiceFlags = ServiceFlags(1 << 6);
151
152    /// NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only serving the last
153    /// 288 (2 day) blocks.
154    /// See BIP159 for details on how this is implemented.
155    pub const NETWORK_LIMITED: ServiceFlags = ServiceFlags(1 << 10);
156
157    // NOTE: When adding new flags, remember to update the Display impl accordingly.
158
159    /// Add [ServiceFlags] together.
160    ///
161    /// Returns itself.
162    pub fn add(&mut self, other: ServiceFlags) -> ServiceFlags {
163        self.0 |= other.0;
164        *self
165    }
166
167    /// Remove [ServiceFlags] from this.
168    ///
169    /// Returns itself.
170    pub fn remove(&mut self, other: ServiceFlags) -> ServiceFlags {
171        self.0 ^= other.0;
172        *self
173    }
174
175    /// Check whether [ServiceFlags] are included in this one.
176    pub fn has(self, flags: ServiceFlags) -> bool {
177        (self.0 | flags.0) == self.0
178    }
179
180    /// Get the integer representation of this [ServiceFlags].
181    pub fn as_u64(self) -> u64 {
182        self.0
183    }
184}
185
186impl fmt::LowerHex for ServiceFlags {
187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188        fmt::LowerHex::fmt(&self.0, f)
189    }
190}
191
192impl fmt::UpperHex for ServiceFlags {
193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194        fmt::UpperHex::fmt(&self.0, f)
195    }
196}
197
198impl fmt::Display for ServiceFlags {
199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200        let mut flags = *self;
201        if flags == ServiceFlags::NONE {
202            return write!(f, "ServiceFlags(NONE)");
203        }
204        let mut first = true;
205        macro_rules! write_flag {
206            ($f:ident) => {
207                if flags.has(ServiceFlags::$f) {
208                    if !first {
209                        write!(f, "|")?;
210                    }
211                    first = false;
212                    write!(f, stringify!($f))?;
213                    flags.remove(ServiceFlags::$f);
214                }
215            }
216        }
217        write!(f, "ServiceFlags(")?;
218        write_flag!(NETWORK);
219        write_flag!(GETUTXO);
220        write_flag!(BLOOM);
221        write_flag!(WITNESS);
222        write_flag!(COMPACT_FILTERS);
223        write_flag!(NETWORK_LIMITED);
224        // If there are unknown flags left, we append them in hex.
225        if flags != ServiceFlags::NONE {
226            if !first {
227                write!(f, "|")?;
228            }
229            write!(f, "0x{:x}", flags)?;
230        }
231        write!(f, ")")
232    }
233}
234
235impl From<u64> for ServiceFlags {
236    fn from(f: u64) -> Self {
237        ServiceFlags(f)
238    }
239}
240
241impl Into<u64> for ServiceFlags {
242    fn into(self) -> u64 {
243        self.0
244    }
245}
246
247impl ops::BitOr for ServiceFlags {
248    type Output = Self;
249
250    fn bitor(mut self, rhs: Self) -> Self {
251        self.add(rhs)
252    }
253}
254
255impl ops::BitOrAssign for ServiceFlags {
256    fn bitor_assign(&mut self, rhs: Self) {
257        self.add(rhs);
258    }
259}
260
261impl ops::BitXor for ServiceFlags {
262    type Output = Self;
263
264    fn bitxor(mut self, rhs: Self) -> Self {
265        self.remove(rhs)
266    }
267}
268
269impl ops::BitXorAssign for ServiceFlags {
270    fn bitxor_assign(&mut self, rhs: Self) {
271        self.remove(rhs);
272    }
273}
274
275impl Encodable for ServiceFlags {
276    #[inline]
277    fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
278        self.0.consensus_encode(&mut s)
279    }
280}
281
282impl Decodable for ServiceFlags {
283    #[inline]
284    fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
285        Ok(ServiceFlags(Decodable::consensus_decode(&mut d)?))
286    }
287}
288
289#[cfg(test)]
290mod tests {
291    use super::{Network, ServiceFlags};
292    use consensus::encode::{deserialize, serialize};
293
294    #[test]
295    fn serialize_test() {
296        assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]);
297        assert_eq!(serialize(&Network::Testnet.magic()), &[0x0b, 0x11, 0x09, 0x07]);
298        assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]);
299        assert_eq!(serialize(&Network::Regtest.magic()), &[0xfa, 0xbf, 0xb5, 0xda]);
300
301        assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin.magic()));
302        assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic()));
303        assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic()));
304        assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic()));
305
306    }
307
308    #[test]
309    fn string_test() {
310        assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
311        assert_eq!(Network::Testnet.to_string(), "testnet");
312        assert_eq!(Network::Regtest.to_string(), "regtest");
313        assert_eq!(Network::Signet.to_string(), "signet");
314
315        assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
316        assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
317        assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
318        assert_eq!("signet".parse::<Network>().unwrap(), Network::Signet);
319        assert!("fakenet".parse::<Network>().is_err());
320    }
321
322    #[test]
323    fn service_flags_test() {
324        let all = [
325            ServiceFlags::NETWORK,
326            ServiceFlags::GETUTXO,
327            ServiceFlags::BLOOM,
328            ServiceFlags::WITNESS,
329            ServiceFlags::COMPACT_FILTERS,
330            ServiceFlags::NETWORK_LIMITED,
331        ];
332
333        let mut flags = ServiceFlags::NONE;
334        for f in all.iter() {
335            assert!(!flags.has(*f));
336        }
337
338        flags |= ServiceFlags::WITNESS;
339        assert_eq!(flags, ServiceFlags::WITNESS);
340
341        let mut flags2 = flags | ServiceFlags::GETUTXO;
342        for f in all.iter() {
343            assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO);
344        }
345
346        flags2 ^= ServiceFlags::WITNESS;
347        assert_eq!(flags2, ServiceFlags::GETUTXO);
348
349        flags2 |= ServiceFlags::COMPACT_FILTERS;
350        flags2 ^= ServiceFlags::GETUTXO;
351        assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS);
352
353        // Test formatting.
354        assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string());
355        assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string());
356        let flag = ServiceFlags::WITNESS | ServiceFlags::BLOOM | ServiceFlags::NETWORK;
357        assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flag.to_string());
358        let flag = ServiceFlags::WITNESS | 0xf0.into();
359        assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
360    }
361}