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 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::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);
|
||||
|
||||
// "bitfield of features to be enabled for this connection"
|
||||
let services = constants::ServiceFlags::NONE;
|
||||
let services = p2p::ServiceFlags::NONE;
|
||||
|
||||
// "standard UNIX timestamp in seconds"
|
||||
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs();
|
||||
|
||||
// "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"
|
||||
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."
|
||||
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::io;
|
||||
use crate::p2p::constants::ServiceFlags;
|
||||
use crate::p2p::ServiceFlags;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// A message which can be sent on the Bitcoin network
|
||||
|
@ -311,7 +311,7 @@ mod test {
|
|||
use super::{AddrV2, AddrV2Message, Address};
|
||||
use crate::consensus::encode::{deserialize, serialize};
|
||||
use crate::internal_macros::hex;
|
||||
use crate::p2p::constants::ServiceFlags;
|
||||
use crate::p2p::ServiceFlags;
|
||||
|
||||
#[test]
|
||||
fn serialize_address_test() {
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
use core::fmt::Display;
|
||||
use core::str::FromStr;
|
||||
use core::{fmt, ops};
|
||||
|
||||
use hex::FromHex;
|
||||
use internals::{debug_from_display, write_err};
|
||||
|
@ -423,161 +423,14 @@ impl fmt::Display for 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)]
|
||||
mod tests {
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::{Magic, Network, ServiceFlags};
|
||||
use super::{Magic, Network};
|
||||
use crate::consensus::encode::{deserialize, serialize};
|
||||
use crate::p2p::ServiceFlags;
|
||||
|
||||
#[test]
|
||||
fn serialize_test() {
|
||||
|
|
|
@ -550,13 +550,14 @@ mod test {
|
|||
use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
|
||||
use crate::internal_macros::hex;
|
||||
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_bloom::{BloomFlags, FilterAdd, FilterLoad};
|
||||
use crate::p2p::message_compact_blocks::{GetBlockTxn, SendCmpct};
|
||||
use crate::p2p::message_filter::{
|
||||
CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters,
|
||||
};
|
||||
use crate::p2p::ServiceFlags;
|
||||
|
||||
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::internal_macros::impl_consensus_encoding;
|
||||
use crate::p2p::address::Address;
|
||||
use crate::p2p::constants::ServiceFlags;
|
||||
use crate::p2p::ServiceFlags;
|
||||
use crate::prelude::*;
|
||||
use crate::{io, p2p};
|
||||
|
||||
|
@ -146,7 +146,7 @@ mod tests {
|
|||
use super::{Reject, RejectReason, VersionMessage};
|
||||
use crate::consensus::encode::{deserialize, serialize};
|
||||
use crate::internal_macros::hex;
|
||||
use crate::p2p::constants::ServiceFlags;
|
||||
use crate::p2p::ServiceFlags;
|
||||
|
||||
#[test]
|
||||
fn version_message_test() {
|
||||
|
|
|
@ -24,7 +24,11 @@ pub mod message_filter;
|
|||
#[cfg(feature = "std")]
|
||||
pub mod message_network;
|
||||
|
||||
use core::{fmt, ops};
|
||||
|
||||
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.
|
||||
///
|
||||
|
@ -44,3 +48,196 @@ pub use self::constants::Magic;
|
|||
/// 60002 - Support `mempool` message
|
||||
/// 60001 - Support `pong` message and nonce in `ping` message
|
||||
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