Merge pull request #345 from stevenroose/serviceflags
Add ServiceFlags type
This commit is contained in:
commit
854718219e
|
@ -22,12 +22,14 @@ use std::io;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||||
|
|
||||||
|
use network::constants::ServiceFlags;
|
||||||
use consensus::encode::{self, Decodable, Encodable};
|
use consensus::encode::{self, Decodable, Encodable};
|
||||||
|
|
||||||
/// A message which can be sent on the Bitcoin network
|
/// A message which can be sent on the Bitcoin network
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
/// Services provided by the peer whose address this is
|
/// Services provided by the peer whose address this is
|
||||||
pub services: u64,
|
pub services: ServiceFlags,
|
||||||
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
|
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
|
||||||
pub address: [u16; 8],
|
pub address: [u16; 8],
|
||||||
/// Network port
|
/// Network port
|
||||||
|
@ -38,7 +40,7 @@ const ONION : [u16; 3] = [0xFD87, 0xD87E, 0xEB43];
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Create an address message for a socket
|
/// Create an address message for a socket
|
||||||
pub fn new (socket :&SocketAddr, services: u64) -> Address {
|
pub fn new (socket :&SocketAddr, services: ServiceFlags) -> Address {
|
||||||
let (address, port) = match socket {
|
let (address, port) = match socket {
|
||||||
&SocketAddr::V4(ref addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()),
|
&SocketAddr::V4(ref addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()),
|
||||||
&SocketAddr::V6(ref addr) => (addr.ip().segments(), addr.port())
|
&SocketAddr::V6(ref addr) => (addr.ip().segments(), addr.port())
|
||||||
|
@ -103,26 +105,6 @@ impl fmt::Debug for Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Address {
|
|
||||||
fn clone(&self) -> Address {
|
|
||||||
Address {
|
|
||||||
services: self.services,
|
|
||||||
address: self.address,
|
|
||||||
port: self.port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for Address {
|
|
||||||
fn eq(&self, other: &Address) -> bool {
|
|
||||||
self.services == other.services &&
|
|
||||||
&self.address[..] == &other.address[..] &&
|
|
||||||
self.port == other.port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for Address {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -134,7 +116,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_address_test() {
|
fn serialize_address_test() {
|
||||||
assert_eq!(serialize(&Address {
|
assert_eq!(serialize(&Address {
|
||||||
services: 1,
|
services: 1.into(),
|
||||||
address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001],
|
address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001],
|
||||||
port: 8333
|
port: 8333
|
||||||
}),
|
}),
|
||||||
|
@ -154,7 +136,7 @@ mod test {
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(full.services, 1);
|
assert_eq!(full.services, 1.into());
|
||||||
assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]);
|
assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]);
|
||||||
assert_eq!(full.port, 8333);
|
assert_eq!(full.port, 8333);
|
||||||
|
|
||||||
|
@ -166,11 +148,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_socket_addr () {
|
fn test_socket_addr () {
|
||||||
let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111,222,123,4)), 5555);
|
let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111,222,123,4)), 5555);
|
||||||
let a4 = Address::new(&s4, 9);
|
let a4 = Address::new(&s4, 9.into());
|
||||||
assert_eq!(a4.socket_addr().unwrap(), s4);
|
assert_eq!(a4.socket_addr().unwrap(), s4);
|
||||||
let s6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444,
|
let s6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444,
|
||||||
0x5555, 0x6666, 0x7777, 0x8888)), 9999);
|
0x5555, 0x6666, 0x7777, 0x8888)), 9999);
|
||||||
let a6 = Address::new(&s6, 9);
|
let a6 = Address::new(&s6, 9.into());
|
||||||
assert_eq!(a6.socket_addr().unwrap(), s6);
|
assert_eq!(a6.socket_addr().unwrap(), s6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +161,7 @@ mod test {
|
||||||
let onionaddr = SocketAddr::new(
|
let onionaddr = SocketAddr::new(
|
||||||
IpAddr::V6(
|
IpAddr::V6(
|
||||||
Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), 1111);
|
Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), 1111);
|
||||||
let addr = Address::new(&onionaddr, 0);
|
let addr = Address::new(&onionaddr, 0.into());
|
||||||
assert!(addr.socket_addr().is_err());
|
assert!(addr.socket_addr().is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,12 @@
|
||||||
//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
|
//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use std::{fmt, 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
|
|
||||||
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! {
|
user_enum! {
|
||||||
/// The cryptocurrency to act on
|
/// The cryptocurrency to act on
|
||||||
|
@ -99,9 +99,176 @@ 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);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the integer representation of this [ServiceFlags].
|
||||||
|
pub fn as_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 {
|
||||||
|
if *self == ServiceFlags::NONE {
|
||||||
|
return write!(f, "ServiceFlags(NONE)");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut flags = self.clone();
|
||||||
|
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!(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 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]
|
||||||
|
@ -144,5 +311,40 @@ mod tests {
|
||||||
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);
|
||||||
|
|
||||||
|
// 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|0xf0)", flag.to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ mod test {
|
||||||
assert_eq!(msg.magic, 0xd9b4bef9);
|
assert_eq!(msg.magic, 0xd9b4bef9);
|
||||||
if let NetworkMessage::Version(version_msg) = msg.payload {
|
if let NetworkMessage::Version(version_msg) = msg.payload {
|
||||||
assert_eq!(version_msg.version, 70015);
|
assert_eq!(version_msg.version, 70015);
|
||||||
assert_eq!(version_msg.services, 1037);
|
assert_eq!(version_msg.services, 1037.into());
|
||||||
assert_eq!(version_msg.timestamp, 1548554224);
|
assert_eq!(version_msg.timestamp, 1548554224);
|
||||||
assert_eq!(version_msg.nonce, 13952548347456104954);
|
assert_eq!(version_msg.nonce, 13952548347456104954);
|
||||||
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
||||||
|
@ -420,7 +420,7 @@ mod test {
|
||||||
assert_eq!(msg.magic, 0xd9b4bef9);
|
assert_eq!(msg.magic, 0xd9b4bef9);
|
||||||
if let NetworkMessage::Version(version_msg) = msg.payload {
|
if let NetworkMessage::Version(version_msg) = msg.payload {
|
||||||
assert_eq!(version_msg.version, 70015);
|
assert_eq!(version_msg.version, 70015);
|
||||||
assert_eq!(version_msg.services, 1037);
|
assert_eq!(version_msg.services, 1037.into());
|
||||||
assert_eq!(version_msg.timestamp, 1548554224);
|
assert_eq!(version_msg.timestamp, 1548554224);
|
||||||
assert_eq!(version_msg.nonce, 13952548347456104954);
|
assert_eq!(version_msg.nonce, 13952548347456104954);
|
||||||
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use network::address::Address;
|
use network::address::Address;
|
||||||
use network::constants;
|
use network::constants::{self, ServiceFlags};
|
||||||
use consensus::{Encodable, Decodable, ReadExt};
|
use consensus::{Encodable, Decodable, ReadExt};
|
||||||
use consensus::encode;
|
use consensus::encode;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -34,7 +34,7 @@ pub struct VersionMessage {
|
||||||
/// The P2P network protocol version
|
/// The P2P network protocol version
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
/// A bitmask describing the services supported by this node
|
/// A bitmask describing the services supported by this node
|
||||||
pub services: u64,
|
pub services: ServiceFlags,
|
||||||
/// The time at which the `version` message was sent
|
/// The time at which the `version` message was sent
|
||||||
pub timestamp: i64,
|
pub timestamp: i64,
|
||||||
/// The network address of the peer receiving the message
|
/// The network address of the peer receiving the message
|
||||||
|
@ -57,7 +57,7 @@ impl VersionMessage {
|
||||||
// TODO: we have fixed services and relay to 0
|
// TODO: we have fixed services and relay to 0
|
||||||
/// Constructs a new `version` message
|
/// Constructs a new `version` message
|
||||||
pub fn new(
|
pub fn new(
|
||||||
services: u64,
|
services: ServiceFlags,
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
receiver: Address,
|
receiver: Address,
|
||||||
sender: Address,
|
sender: Address,
|
||||||
|
@ -159,7 +159,7 @@ mod tests {
|
||||||
assert!(decode.is_ok());
|
assert!(decode.is_ok());
|
||||||
let real_decode = decode.unwrap();
|
let real_decode = decode.unwrap();
|
||||||
assert_eq!(real_decode.version, 70002);
|
assert_eq!(real_decode.version, 70002);
|
||||||
assert_eq!(real_decode.services, 1);
|
assert_eq!(real_decode.services, 1.into());
|
||||||
assert_eq!(real_decode.timestamp, 1401217254);
|
assert_eq!(real_decode.timestamp, 1401217254);
|
||||||
// address decodes should be covered by Address tests
|
// address decodes should be covered by Address tests
|
||||||
assert_eq!(real_decode.nonce, 16735069437859780935);
|
assert_eq!(real_decode.nonce, 16735069437859780935);
|
||||||
|
|
|
@ -25,6 +25,7 @@ use std::error;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
|
|
||||||
pub mod address;
|
pub mod address;
|
||||||
|
pub use self::address::Address;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod message_blockdata;
|
pub mod message_blockdata;
|
||||||
pub mod message_network;
|
pub mod message_network;
|
||||||
|
|
|
@ -156,7 +156,7 @@ mod test {
|
||||||
assert_eq!(msg.magic, 0xd9b4bef9);
|
assert_eq!(msg.magic, 0xd9b4bef9);
|
||||||
if let NetworkMessage::Version(ref version_msg) = msg.payload {
|
if let NetworkMessage::Version(ref version_msg) = msg.payload {
|
||||||
assert_eq!(version_msg.version, 70015);
|
assert_eq!(version_msg.version, 70015);
|
||||||
assert_eq!(version_msg.services, 1037);
|
assert_eq!(version_msg.services, 1037.into());
|
||||||
assert_eq!(version_msg.timestamp, 1548554224);
|
assert_eq!(version_msg.timestamp, 1548554224);
|
||||||
assert_eq!(version_msg.nonce, 13952548347456104954);
|
assert_eq!(version_msg.nonce, 13952548347456104954);
|
||||||
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
|
||||||
|
|
Loading…
Reference in New Issue