Add ServiceFlags type
This commit is contained in:
parent
885fc39f48
commit
fdf4b2f74e
|
@ -37,6 +37,10 @@
|
||||||
//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
|
//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use std::{io, ops};
|
||||||
|
|
||||||
|
use consensus::encode::{self, Encodable, Decodable};
|
||||||
|
|
||||||
/// Version of the protocol as appearing in network message headers
|
/// Version of the protocol as appearing in network message headers
|
||||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||||
/// Bitfield of services provided by this node
|
/// Bitfield of services provided by this node
|
||||||
|
@ -99,9 +103,125 @@ impl Network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flags to indicate which network services a node supports.
|
||||||
|
#[derive(Debug, Clone, Copy, 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);
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the integer representation of this [ServiceFlags].
|
||||||
|
pub fn as_u64(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for ServiceFlags {
|
||||||
|
fn from(f: u64) -> Self {
|
||||||
|
ServiceFlags(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u64> for ServiceFlags {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
self.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<S: io::Write>(
|
||||||
|
&self,
|
||||||
|
mut s: S,
|
||||||
|
) -> Result<usize, encode::Error> {
|
||||||
|
self.0.consensus_encode(&mut s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for ServiceFlags {
|
||||||
|
#[inline]
|
||||||
|
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||||
|
Ok(ServiceFlags(Decodable::consensus_decode(&mut d)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Network;
|
use super::{Network, ServiceFlags};
|
||||||
use consensus::encode::{deserialize, serialize};
|
use consensus::encode::{deserialize, serialize};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -133,16 +253,43 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_test() {
|
fn string_test() {
|
||||||
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
||||||
assert_eq!(Network::Testnet.to_string(), "testnet");
|
assert_eq!(Network::Testnet.to_string(), "testnet");
|
||||||
assert_eq!(Network::Regtest.to_string(), "regtest");
|
assert_eq!(Network::Regtest.to_string(), "regtest");
|
||||||
|
|
||||||
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
||||||
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
||||||
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
||||||
assert!("fakenet".parse::<Network>().is_err());
|
assert!("fakenet".parse::<Network>().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn service_flags_test() {
|
||||||
|
let all = [
|
||||||
|
ServiceFlags::NETWORK,
|
||||||
|
ServiceFlags::GETUTXO,
|
||||||
|
ServiceFlags::BLOOM,
|
||||||
|
ServiceFlags::WITNESS,
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue