From 7ecb6b9deab96e458c4673a153b8df49a98d3a99 Mon Sep 17 00:00:00 2001 From: Jean Pierre Dudey Date: Fri, 10 Aug 2018 13:09:22 -0400 Subject: [PATCH] Refactor and add more documentation for the `Network` type. Signed-off-by: Jean Pierre Dudey --- src/network/constants.rs | 104 +++++++++++++++++++++++++++++---------- src/network/socket.rs | 4 +- 2 files changed, 79 insertions(+), 29 deletions(-) diff --git a/src/network/constants.rs b/src/network/constants.rs index bdd6fac..8f6c349 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -12,63 +12,113 @@ // If not, see . // -//! # Network constants +//! Network constants //! //! This module provides various constants relating to the Bitcoin network //! protocol, such as protocol versioning and magic header bytes. //! +//! The [`Network`][1] type implements the [`ConsensusDecodable`][2] and +//! [`ConsensusEncodable`][3] and encodes the magic bytes of the given +//! network +//! +//! [1]: enum.Network.html +//! [2]: ../encodable/trait.ConsensusDecodable.html +//! [3]: ../encodable/trait.ConsensusEncodable.html +//! +//! # Example: encoding a network's magic bytes +//! +//! ```rust +//! use bitcoin::network::constants::Network; +//! use bitcoin::network::serialize::serialize; +//! +//! let network = Network::Bitcoin; +//! let bytes = serialize(&network).unwrap(); +//! +//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); +//! ``` use network::encodable::{ConsensusDecodable, ConsensusEncodable}; use network::serialize::{SimpleEncoder, SimpleDecoder}; +/// Version of the protocol as appearing in network message headers +pub const PROTOCOL_VERSION: u32 = 70001; +/// Bitfield of services provided by this node +pub const SERVICES: u64 = 0; +/// User agent as it appears in the version message +pub const USER_AGENT: &'static str = "bitcoin-rust v0.1"; + user_enum! { + /// The cryptocurrency to act on #[derive(Copy, PartialEq, Eq, Clone, Hash)] - #[doc="The cryptocurrency to act on"] pub enum Network { - #[doc="Classic Bitcoin"] + /// Classic Bitcoin Bitcoin <-> "bitcoin", - #[doc="Bitcoin's testnet"] + /// Bitcoin's testnet Testnet <-> "testnet", - #[doc="Bitcoin's regtest"] + /// Bitcoin's regtest Regtest <-> "regtest" } } -/// Version of the protocol as appearing in network message headers -pub const PROTOCOL_VERSION: u32 = 70001; -/// Bitfield of services provided by this node -pub const SERVICES: u64 = 0; -/// User agent as it appears in the version message -pub const USER_AGENT: &'static str = "bitcoin-rust v0.1"; +impl Network { + /// Creates a `Network` from the magic bytes. + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::network::constants::Network; + /// + /// assert_eq!(Some(Network::Bitcoin), Network::from_magic(0xD9B4BEF9)); + /// assert_eq!(None, Network::from_magic(0xFFFFFFFF)); + /// ``` + pub fn from_magic(magic: u32) -> Option { + // Note: any new entries here must be added to `magic` below + match magic { + 0xD9B4BEF9 => Some(Network::Bitcoin), + 0x0709110B => Some(Network::Testnet), + 0xDAB5BFFA => Some(Network::Regtest), + _ => None + } + } -/// Return the network magic bytes, which should be encoded little-endian -/// at the start of every message -pub fn magic(network: Network) -> u32 { - match network { - Network::Bitcoin => 0xD9B4BEF9, - Network::Testnet => 0x0709110B, - Network::Regtest => 0xDAB5BFFA, - // Note: any new entries here must be added to `consensus_decode` below + /// Return the network magic bytes, which should be encoded little-endian + /// at the start of every message + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::network::constants::Network; + /// + /// let network = Network::Bitcoin; + /// assert_eq!(network.magic(), 0xD9B4BEF9); + /// ``` + pub fn magic(&self) -> u32 { + // Note: any new entries here must be added to `from_magic` above + match *self { + Network::Bitcoin => 0xD9B4BEF9, + Network::Testnet => 0x0709110B, + Network::Regtest => 0xDAB5BFFA, + } } } impl ConsensusEncodable for Network { + /// Encodes the magic bytes of `Network`. #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { - magic(*self).consensus_encode(s) + self.magic().consensus_encode(s) } } impl ConsensusDecodable for Network { + /// Decodes the magic bytes of `Network`. #[inline] fn consensus_decode(d: &mut D) -> Result { - let magic: u32 = try!(ConsensusDecodable::consensus_decode(d)); - match magic { - 0xD9B4BEF9 => Ok(Network::Bitcoin), - 0x0709110B => Ok(Network::Testnet), - 0xDAB5BFFA => Ok(Network::Regtest), - x => Err(d.error(format!("Unknown network (magic {:x})", x))) - } + u32::consensus_decode(d) + .and_then(|m| { + Network::from_magic(m) + .ok_or(d.error(format!("Unknown network (magic {:x})", m))) + }) } } diff --git a/src/network/socket.rs b/src/network/socket.rs index a012666..1bb45f7 100644 --- a/src/network/socket.rs +++ b/src/network/socket.rs @@ -52,7 +52,7 @@ pub struct Socket { /// Nonce to identify our `version` messages pub version_nonce: u64, /// Network magic - pub magic: u32 + pub magic: u32 } macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({ @@ -90,7 +90,7 @@ impl Socket { services: 0, version_nonce: rng.gen(), user_agent: constants::USER_AGENT.to_owned(), - magic: constants::magic(network) + magic: network.magic(), } }