Move p2p::constants::ServiceFlags to p2p module
The `ServiceFlags` type is used by the p2p layer. It can live in the `mod.rs` file of the `p2p` module. Done in preparation for removing the `p2p::constants` module. This is a straight code move, the `ServiceFlags` replaces the current re-export.
This commit is contained in:
parent
99d8ae1173
commit
d9d5a4ed4f
|
@ -6,7 +6,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use std::{env, process};
|
use std::{env, process};
|
||||||
|
|
||||||
use bitcoin::consensus::{encode, Decodable};
|
use bitcoin::consensus::{encode, Decodable};
|
||||||
use bitcoin::p2p::{address, constants, message, message_network};
|
use bitcoin::p2p::{self, address, constants, message, message_network};
|
||||||
use bitcoin::secp256k1;
|
use bitcoin::secp256k1;
|
||||||
use bitcoin::secp256k1::rand::Rng;
|
use bitcoin::secp256k1::rand::Rng;
|
||||||
|
|
||||||
|
@ -75,16 +75,16 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
|
||||||
let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
|
let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
|
||||||
|
|
||||||
// "bitfield of features to be enabled for this connection"
|
// "bitfield of features to be enabled for this connection"
|
||||||
let services = constants::ServiceFlags::NONE;
|
let services = p2p::ServiceFlags::NONE;
|
||||||
|
|
||||||
// "standard UNIX timestamp in seconds"
|
// "standard UNIX timestamp in seconds"
|
||||||
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs();
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs();
|
||||||
|
|
||||||
// "The network address of the node receiving this message"
|
// "The network address of the node receiving this message"
|
||||||
let addr_recv = address::Address::new(&address, constants::ServiceFlags::NONE);
|
let addr_recv = address::Address::new(&address, p2p::ServiceFlags::NONE);
|
||||||
|
|
||||||
// "The network address of the node emitting this message"
|
// "The network address of the node emitting this message"
|
||||||
let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE);
|
let addr_from = address::Address::new(&my_address, p2p::ServiceFlags::NONE);
|
||||||
|
|
||||||
// "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self."
|
// "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self."
|
||||||
let nonce: u64 = secp256k1::rand::thread_rng().gen();
|
let nonce: u64 = secp256k1::rand::thread_rng().gen();
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSoc
|
||||||
|
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable, ReadExt, VarInt, WriteExt};
|
use crate::consensus::encode::{self, Decodable, Encodable, ReadExt, VarInt, WriteExt};
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::p2p::constants::ServiceFlags;
|
use crate::p2p::ServiceFlags;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// A message which can be sent on the Bitcoin network
|
/// A message which can be sent on the Bitcoin network
|
||||||
|
@ -311,7 +311,7 @@ mod test {
|
||||||
use super::{AddrV2, AddrV2Message, Address};
|
use super::{AddrV2, AddrV2Message, Address};
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
use crate::p2p::constants::ServiceFlags;
|
use crate::p2p::ServiceFlags;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_address_test() {
|
fn serialize_address_test() {
|
||||||
|
|
|
@ -27,9 +27,9 @@
|
||||||
|
|
||||||
use core::borrow::{Borrow, BorrowMut};
|
use core::borrow::{Borrow, BorrowMut};
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
use core::fmt;
|
||||||
use core::fmt::Display;
|
use core::fmt::Display;
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use core::{fmt, ops};
|
|
||||||
|
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
use internals::{debug_from_display, write_err};
|
use internals::{debug_from_display, write_err};
|
||||||
|
@ -423,161 +423,14 @@ impl fmt::Display for UnknownMagic {
|
||||||
}
|
}
|
||||||
impl_std_error!(UnknownMagic);
|
impl_std_error!(UnknownMagic);
|
||||||
|
|
||||||
/// Flags to indicate which network services a node supports.
|
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct ServiceFlags(u64);
|
|
||||||
|
|
||||||
impl ServiceFlags {
|
|
||||||
/// NONE means no services supported.
|
|
||||||
pub const NONE: ServiceFlags = ServiceFlags(0);
|
|
||||||
|
|
||||||
/// NETWORK means that the node is capable of serving the complete block chain. It is currently
|
|
||||||
/// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light
|
|
||||||
/// clients.
|
|
||||||
pub const NETWORK: ServiceFlags = ServiceFlags(1 << 0);
|
|
||||||
|
|
||||||
/// GETUTXO means the node is capable of responding to the getutxo protocol request. Bitcoin
|
|
||||||
/// Core does not support this but a patch set called Bitcoin XT does.
|
|
||||||
/// See BIP 64 for details on how this is implemented.
|
|
||||||
pub const GETUTXO: ServiceFlags = ServiceFlags(1 << 1);
|
|
||||||
|
|
||||||
/// BLOOM means the node is capable and willing to handle bloom-filtered connections. Bitcoin
|
|
||||||
/// Core nodes used to support this by default, without advertising this bit, but no longer do
|
|
||||||
/// as of protocol version 70011 (= NO_BLOOM_VERSION)
|
|
||||||
pub const BLOOM: ServiceFlags = ServiceFlags(1 << 2);
|
|
||||||
|
|
||||||
/// WITNESS indicates that a node can be asked for blocks and transactions including witness
|
|
||||||
/// data.
|
|
||||||
pub const WITNESS: ServiceFlags = ServiceFlags(1 << 3);
|
|
||||||
|
|
||||||
/// COMPACT_FILTERS means the node will service basic block filter requests.
|
|
||||||
/// See BIP157 and BIP158 for details on how this is implemented.
|
|
||||||
pub const COMPACT_FILTERS: ServiceFlags = ServiceFlags(1 << 6);
|
|
||||||
|
|
||||||
/// NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only serving the last
|
|
||||||
/// 288 (2 day) blocks.
|
|
||||||
/// See BIP159 for details on how this is implemented.
|
|
||||||
pub const NETWORK_LIMITED: ServiceFlags = ServiceFlags(1 << 10);
|
|
||||||
|
|
||||||
// NOTE: When adding new flags, remember to update the Display impl accordingly.
|
|
||||||
|
|
||||||
/// Add [ServiceFlags] together.
|
|
||||||
///
|
|
||||||
/// Returns itself.
|
|
||||||
pub fn add(&mut self, other: ServiceFlags) -> ServiceFlags {
|
|
||||||
self.0 |= other.0;
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove [ServiceFlags] from this.
|
|
||||||
///
|
|
||||||
/// Returns itself.
|
|
||||||
pub fn remove(&mut self, other: ServiceFlags) -> ServiceFlags {
|
|
||||||
self.0 ^= other.0;
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check whether [ServiceFlags] are included in this one.
|
|
||||||
pub fn has(self, flags: ServiceFlags) -> bool { (self.0 | flags.0) == self.0 }
|
|
||||||
|
|
||||||
/// Gets the integer representation of this [`ServiceFlags`].
|
|
||||||
pub fn to_u64(self) -> u64 { self.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::LowerHex for ServiceFlags {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::UpperHex for ServiceFlags {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ServiceFlags {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let mut flags = *self;
|
|
||||||
if flags == ServiceFlags::NONE {
|
|
||||||
return write!(f, "ServiceFlags(NONE)");
|
|
||||||
}
|
|
||||||
let mut first = true;
|
|
||||||
macro_rules! write_flag {
|
|
||||||
($f:ident) => {
|
|
||||||
if flags.has(ServiceFlags::$f) {
|
|
||||||
if !first {
|
|
||||||
write!(f, "|")?;
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
write!(f, stringify!($f))?;
|
|
||||||
flags.remove(ServiceFlags::$f);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
write!(f, "ServiceFlags(")?;
|
|
||||||
write_flag!(NETWORK);
|
|
||||||
write_flag!(GETUTXO);
|
|
||||||
write_flag!(BLOOM);
|
|
||||||
write_flag!(WITNESS);
|
|
||||||
write_flag!(COMPACT_FILTERS);
|
|
||||||
write_flag!(NETWORK_LIMITED);
|
|
||||||
// If there are unknown flags left, we append them in hex.
|
|
||||||
if flags != ServiceFlags::NONE {
|
|
||||||
if !first {
|
|
||||||
write!(f, "|")?;
|
|
||||||
}
|
|
||||||
write!(f, "0x{:x}", flags)?;
|
|
||||||
}
|
|
||||||
write!(f, ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u64> for ServiceFlags {
|
|
||||||
fn from(f: u64) -> Self { ServiceFlags(f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ServiceFlags> for u64 {
|
|
||||||
fn from(flags: ServiceFlags) -> Self { flags.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::BitOr for ServiceFlags {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn bitor(mut self, rhs: Self) -> Self { self.add(rhs) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::BitOrAssign for ServiceFlags {
|
|
||||||
fn bitor_assign(&mut self, rhs: Self) { self.add(rhs); }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::BitXor for ServiceFlags {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn bitxor(mut self, rhs: Self) -> Self { self.remove(rhs) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::BitXorAssign for ServiceFlags {
|
|
||||||
fn bitxor_assign(&mut self, rhs: Self) { self.remove(rhs); }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encodable for ServiceFlags {
|
|
||||||
#[inline]
|
|
||||||
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
|
||||||
self.0.consensus_encode(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for ServiceFlags {
|
|
||||||
#[inline]
|
|
||||||
fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
|
||||||
Ok(ServiceFlags(Decodable::consensus_decode(r)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::{Magic, Network, ServiceFlags};
|
use super::{Magic, Network};
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
|
use crate::p2p::ServiceFlags;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_test() {
|
fn serialize_test() {
|
||||||
|
|
|
@ -550,13 +550,14 @@ mod test {
|
||||||
use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
|
use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
use crate::p2p::address::{AddrV2, AddrV2Message, Address};
|
use crate::p2p::address::{AddrV2, AddrV2Message, Address};
|
||||||
use crate::p2p::constants::{Magic, Network, ServiceFlags};
|
use crate::p2p::constants::{Magic, Network};
|
||||||
use crate::p2p::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory};
|
use crate::p2p::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory};
|
||||||
use crate::p2p::message_bloom::{BloomFlags, FilterAdd, FilterLoad};
|
use crate::p2p::message_bloom::{BloomFlags, FilterAdd, FilterLoad};
|
||||||
use crate::p2p::message_compact_blocks::{GetBlockTxn, SendCmpct};
|
use crate::p2p::message_compact_blocks::{GetBlockTxn, SendCmpct};
|
||||||
use crate::p2p::message_filter::{
|
use crate::p2p::message_filter::{
|
||||||
CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters,
|
CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters,
|
||||||
};
|
};
|
||||||
|
use crate::p2p::ServiceFlags;
|
||||||
|
|
||||||
fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() }
|
fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() }
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use hashes::sha256d;
|
||||||
use crate::consensus::{encode, Decodable, Encodable, ReadExt};
|
use crate::consensus::{encode, Decodable, Encodable, ReadExt};
|
||||||
use crate::internal_macros::impl_consensus_encoding;
|
use crate::internal_macros::impl_consensus_encoding;
|
||||||
use crate::p2p::address::Address;
|
use crate::p2p::address::Address;
|
||||||
use crate::p2p::constants::ServiceFlags;
|
use crate::p2p::ServiceFlags;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{io, p2p};
|
use crate::{io, p2p};
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ mod tests {
|
||||||
use super::{Reject, RejectReason, VersionMessage};
|
use super::{Reject, RejectReason, VersionMessage};
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
use crate::p2p::constants::ServiceFlags;
|
use crate::p2p::ServiceFlags;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_message_test() {
|
fn version_message_test() {
|
||||||
|
|
|
@ -24,7 +24,11 @@ pub mod message_filter;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod message_network;
|
pub mod message_network;
|
||||||
|
|
||||||
|
use core::{fmt, ops};
|
||||||
|
|
||||||
pub use self::constants::Magic;
|
pub use self::constants::Magic;
|
||||||
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
|
use crate::io;
|
||||||
|
|
||||||
/// Version of the protocol as appearing in network message headers.
|
/// Version of the protocol as appearing in network message headers.
|
||||||
///
|
///
|
||||||
|
@ -44,3 +48,196 @@ pub use self::constants::Magic;
|
||||||
/// 60002 - Support `mempool` message
|
/// 60002 - Support `mempool` message
|
||||||
/// 60001 - Support `pong` message and nonce in `ping` message
|
/// 60001 - Support `pong` message and nonce in `ping` message
|
||||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||||
|
|
||||||
|
/// Flags to indicate which network services a node supports.
|
||||||
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct ServiceFlags(u64);
|
||||||
|
|
||||||
|
impl ServiceFlags {
|
||||||
|
/// NONE means no services supported.
|
||||||
|
pub const NONE: ServiceFlags = ServiceFlags(0);
|
||||||
|
|
||||||
|
/// NETWORK means that the node is capable of serving the complete block chain. It is currently
|
||||||
|
/// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light
|
||||||
|
/// clients.
|
||||||
|
pub const NETWORK: ServiceFlags = ServiceFlags(1 << 0);
|
||||||
|
|
||||||
|
/// GETUTXO means the node is capable of responding to the getutxo protocol request. Bitcoin
|
||||||
|
/// Core does not support this but a patch set called Bitcoin XT does.
|
||||||
|
/// See BIP 64 for details on how this is implemented.
|
||||||
|
pub const GETUTXO: ServiceFlags = ServiceFlags(1 << 1);
|
||||||
|
|
||||||
|
/// BLOOM means the node is capable and willing to handle bloom-filtered connections. Bitcoin
|
||||||
|
/// Core nodes used to support this by default, without advertising this bit, but no longer do
|
||||||
|
/// as of protocol version 70011 (= NO_BLOOM_VERSION)
|
||||||
|
pub const BLOOM: ServiceFlags = ServiceFlags(1 << 2);
|
||||||
|
|
||||||
|
/// WITNESS indicates that a node can be asked for blocks and transactions including witness
|
||||||
|
/// data.
|
||||||
|
pub const WITNESS: ServiceFlags = ServiceFlags(1 << 3);
|
||||||
|
|
||||||
|
/// COMPACT_FILTERS means the node will service basic block filter requests.
|
||||||
|
/// See BIP157 and BIP158 for details on how this is implemented.
|
||||||
|
pub const COMPACT_FILTERS: ServiceFlags = ServiceFlags(1 << 6);
|
||||||
|
|
||||||
|
/// NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only serving the last
|
||||||
|
/// 288 (2 day) blocks.
|
||||||
|
/// See BIP159 for details on how this is implemented.
|
||||||
|
pub const NETWORK_LIMITED: ServiceFlags = ServiceFlags(1 << 10);
|
||||||
|
|
||||||
|
// NOTE: When adding new flags, remember to update the Display impl accordingly.
|
||||||
|
|
||||||
|
/// Add [ServiceFlags] together.
|
||||||
|
///
|
||||||
|
/// Returns itself.
|
||||||
|
pub fn add(&mut self, other: ServiceFlags) -> ServiceFlags {
|
||||||
|
self.0 |= other.0;
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove [ServiceFlags] from this.
|
||||||
|
///
|
||||||
|
/// Returns itself.
|
||||||
|
pub fn remove(&mut self, other: ServiceFlags) -> ServiceFlags {
|
||||||
|
self.0 ^= other.0;
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether [ServiceFlags] are included in this one.
|
||||||
|
pub fn has(self, flags: ServiceFlags) -> bool { (self.0 | flags.0) == self.0 }
|
||||||
|
|
||||||
|
/// Gets the integer representation of this [`ServiceFlags`].
|
||||||
|
pub fn to_u64(self) -> u64 { self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::LowerHex for ServiceFlags {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::UpperHex for ServiceFlags {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ServiceFlags {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut flags = *self;
|
||||||
|
if flags == ServiceFlags::NONE {
|
||||||
|
return write!(f, "ServiceFlags(NONE)");
|
||||||
|
}
|
||||||
|
let mut first = true;
|
||||||
|
macro_rules! write_flag {
|
||||||
|
($f:ident) => {
|
||||||
|
if flags.has(ServiceFlags::$f) {
|
||||||
|
if !first {
|
||||||
|
write!(f, "|")?;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
write!(f, stringify!($f))?;
|
||||||
|
flags.remove(ServiceFlags::$f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
write!(f, "ServiceFlags(")?;
|
||||||
|
write_flag!(NETWORK);
|
||||||
|
write_flag!(GETUTXO);
|
||||||
|
write_flag!(BLOOM);
|
||||||
|
write_flag!(WITNESS);
|
||||||
|
write_flag!(COMPACT_FILTERS);
|
||||||
|
write_flag!(NETWORK_LIMITED);
|
||||||
|
// If there are unknown flags left, we append them in hex.
|
||||||
|
if flags != ServiceFlags::NONE {
|
||||||
|
if !first {
|
||||||
|
write!(f, "|")?;
|
||||||
|
}
|
||||||
|
write!(f, "0x{:x}", flags)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for ServiceFlags {
|
||||||
|
fn from(f: u64) -> Self { ServiceFlags(f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ServiceFlags> for u64 {
|
||||||
|
fn from(flags: ServiceFlags) -> Self { flags.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::BitOr for ServiceFlags {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitor(mut self, rhs: Self) -> Self { self.add(rhs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::BitOrAssign for ServiceFlags {
|
||||||
|
fn bitor_assign(&mut self, rhs: Self) { self.add(rhs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::BitXor for ServiceFlags {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitxor(mut self, rhs: Self) -> Self { self.remove(rhs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::BitXorAssign for ServiceFlags {
|
||||||
|
fn bitxor_assign(&mut self, rhs: Self) { self.remove(rhs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for ServiceFlags {
|
||||||
|
#[inline]
|
||||||
|
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
|
self.0.consensus_encode(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for ServiceFlags {
|
||||||
|
#[inline]
|
||||||
|
fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
|
Ok(ServiceFlags(Decodable::consensus_decode(r)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn service_flags_test() {
|
||||||
|
let all = [
|
||||||
|
ServiceFlags::NETWORK,
|
||||||
|
ServiceFlags::GETUTXO,
|
||||||
|
ServiceFlags::BLOOM,
|
||||||
|
ServiceFlags::WITNESS,
|
||||||
|
ServiceFlags::COMPACT_FILTERS,
|
||||||
|
ServiceFlags::NETWORK_LIMITED,
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut flags = ServiceFlags::NONE;
|
||||||
|
for f in all.iter() {
|
||||||
|
assert!(!flags.has(*f));
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= ServiceFlags::WITNESS;
|
||||||
|
assert_eq!(flags, ServiceFlags::WITNESS);
|
||||||
|
|
||||||
|
let mut flags2 = flags | ServiceFlags::GETUTXO;
|
||||||
|
for f in all.iter() {
|
||||||
|
assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags2 ^= ServiceFlags::WITNESS;
|
||||||
|
assert_eq!(flags2, ServiceFlags::GETUTXO);
|
||||||
|
|
||||||
|
flags2 |= ServiceFlags::COMPACT_FILTERS;
|
||||||
|
flags2 ^= ServiceFlags::GETUTXO;
|
||||||
|
assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS);
|
||||||
|
|
||||||
|
// Test formatting.
|
||||||
|
assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string());
|
||||||
|
assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string());
|
||||||
|
let flag = ServiceFlags::WITNESS | ServiceFlags::BLOOM | ServiceFlags::NETWORK;
|
||||||
|
assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flag.to_string());
|
||||||
|
let flag = ServiceFlags::WITNESS | 0xf0.into();
|
||||||
|
assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue