Skip to main content

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