Add ServiceFlags type
This commit is contained in:
parent
885fc39f48
commit
fdf4b2f74e
|
@ -37,6 +37,10 @@
|
|||
//! 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
|
||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||
/// 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)]
|
||||
mod tests {
|
||||
use super::Network;
|
||||
use super::{Network, ServiceFlags};
|
||||
use consensus::encode::{deserialize, serialize};
|
||||
|
||||
#[test]
|
||||
|
@ -133,16 +253,43 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_test() {
|
||||
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
||||
assert_eq!(Network::Testnet.to_string(), "testnet");
|
||||
assert_eq!(Network::Regtest.to_string(), "regtest");
|
||||
#[test]
|
||||
fn string_test() {
|
||||
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
||||
assert_eq!(Network::Testnet.to_string(), "testnet");
|
||||
assert_eq!(Network::Regtest.to_string(), "regtest");
|
||||
|
||||
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
||||
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
||||
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
||||
assert!("fakenet".parse::<Network>().is_err());
|
||||
}
|
||||
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
||||
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
||||
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
||||
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