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