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);
36//!
37//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
38//! ```
39
40use consensus::encode::{Decodable, Encodable};
41use consensus::encode::{self, Encoder, Decoder};
42
43/// Version of the protocol as appearing in network message headers
44pub const PROTOCOL_VERSION: u32 = 70001;
45/// Bitfield of services provided by this node
46pub const SERVICES: u64 = 0;
47/// User agent as it appears in the version message
48pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";
49
50user_enum! {
51    /// The cryptocurrency to act on
52    #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
53    pub enum Network {
54        /// Classic Bitcoin
55        Bitcoin <-> "bitcoin",
56        /// Bitcoin's testnet
57        Testnet <-> "testnet",
58        /// Bitcoin's regtest
59        Regtest <-> "regtest"
60    }
61}
62
63impl Network {
64    /// Creates a `Network` from the magic bytes.
65    ///
66    /// # Examples
67    ///
68    /// ```rust
69    /// use bitcoin::network::constants::Network;
70    ///
71    /// assert_eq!(Some(Network::Bitcoin), Network::from_magic(0xD9B4BEF9));
72    /// assert_eq!(None, Network::from_magic(0xFFFFFFFF));
73    /// ```
74    pub fn from_magic(magic: u32) -> Option<Network> {
75        // Note: any new entries here must be added to `magic` below
76        match magic {
77            0xD9B4BEF9 => Some(Network::Bitcoin),
78            0x0709110B => Some(Network::Testnet),
79            0xDAB5BFFA => Some(Network::Regtest),
80            _ => None
81        }
82    }
83
84    /// Return the network magic bytes, which should be encoded little-endian
85    /// at the start of every message
86    ///
87    /// # Examples
88    ///
89    /// ```rust
90    /// use bitcoin::network::constants::Network;
91    ///
92    /// let network = Network::Bitcoin;
93    /// assert_eq!(network.magic(), 0xD9B4BEF9);
94    /// ```
95    pub fn magic(&self) -> u32 {
96        // Note: any new entries here must be added to `from_magic` above
97        match *self {
98            Network::Bitcoin => 0xD9B4BEF9,
99            Network::Testnet => 0x0709110B,
100            Network::Regtest => 0xDAB5BFFA,
101        }
102    }
103}
104
105impl<S: Encoder> Encodable<S> for Network {
106    /// Encodes the magic bytes of `Network`.
107    #[inline]
108    fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
109        self.magic().consensus_encode(s)
110    }
111}
112
113impl<D: Decoder> Decodable<D> for Network {
114    /// Decodes the magic bytes of `Network`.
115    #[inline]
116    fn consensus_decode(d: &mut D) -> Result<Network, encode::Error> {
117        u32::consensus_decode(d)
118            .and_then(|m| {
119                Network::from_magic(m)
120                    .ok_or(encode::Error::UnknownNetworkMagic(m))
121            })
122    }
123}
124
125#[cfg(test)]
126mod tests {
127  use super::Network;
128  use consensus::encode::{deserialize, serialize};
129
130  #[test]
131  fn serialize_test() {
132    assert_eq!(serialize(&Network::Bitcoin), vec![0xf9, 0xbe, 0xb4, 0xd9]);
133    assert_eq!(serialize(&Network::Testnet), vec![0x0b, 0x11, 0x09, 0x07]);
134    assert_eq!(serialize(&Network::Regtest), vec![0xfa, 0xbf, 0xb5, 0xda]);
135
136    assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin));
137    assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet));
138    assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest));
139
140    let bad: Result<Network, _> = deserialize("fakenet".as_bytes());
141    assert!(bad.is_err());
142  }
143
144  #[test]
145  fn string_test() {
146      assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
147      assert_eq!(Network::Testnet.to_string(), "testnet");
148      assert_eq!(Network::Regtest.to_string(), "regtest");
149
150      assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
151      assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
152      assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
153      assert!("fakenet".parse::<Network>().is_err());
154  }
155}
156