Replace PeerServices(u64) with a bitflags struct.
This gives considerably better ergonomics.
This commit is contained in:
parent
9603a29399
commit
f5dca597dd
|
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitflags = "1.2"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
byteorder = "1.3"
|
byteorder = "1.3"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
|
|
||||||
mod network;
|
mod network;
|
||||||
pub use network::Network;
|
pub use network::Network;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pub struct MetaAddr {
|
||||||
impl ZcashSerialize for MetaAddr {
|
impl ZcashSerialize for MetaAddr {
|
||||||
fn zcash_serialize<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
|
fn zcash_serialize<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
|
||||||
writer.write_u32::<LittleEndian>(self.last_seen.timestamp() as u32)?;
|
writer.write_u32::<LittleEndian>(self.last_seen.timestamp() as u32)?;
|
||||||
writer.write_u64::<LittleEndian>(self.services.0)?;
|
writer.write_u64::<LittleEndian>(self.services.bits())?;
|
||||||
writer.write_socket_addr(self.addr)?;
|
writer.write_socket_addr(self.addr)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +41,8 @@ impl ZcashDeserialize for MetaAddr {
|
||||||
fn zcash_deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
|
fn zcash_deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
|
||||||
Ok(MetaAddr {
|
Ok(MetaAddr {
|
||||||
last_seen: Utc.timestamp(reader.read_u32::<LittleEndian>()? as i64, 0),
|
last_seen: Utc.timestamp(reader.read_u32::<LittleEndian>()? as i64, 0),
|
||||||
services: PeerServices(reader.read_u64::<LittleEndian>()?),
|
// Discard unknown service bits.
|
||||||
|
services: PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
|
||||||
addr: reader.read_socket_addr()?,
|
addr: reader.read_socket_addr()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,15 +174,15 @@ impl Codec {
|
||||||
ref relay,
|
ref relay,
|
||||||
} => {
|
} => {
|
||||||
writer.write_u32::<LittleEndian>(version.0)?;
|
writer.write_u32::<LittleEndian>(version.0)?;
|
||||||
writer.write_u64::<LittleEndian>(services.0)?;
|
writer.write_u64::<LittleEndian>(services.bits())?;
|
||||||
writer.write_i64::<LittleEndian>(timestamp.timestamp())?;
|
writer.write_i64::<LittleEndian>(timestamp.timestamp())?;
|
||||||
|
|
||||||
let (recv_services, recv_addr) = address_recv;
|
let (recv_services, recv_addr) = address_recv;
|
||||||
writer.write_u64::<LittleEndian>(recv_services.0)?;
|
writer.write_u64::<LittleEndian>(recv_services.bits())?;
|
||||||
writer.write_socket_addr(*recv_addr)?;
|
writer.write_socket_addr(*recv_addr)?;
|
||||||
|
|
||||||
let (from_services, from_addr) = address_from;
|
let (from_services, from_addr) = address_from;
|
||||||
writer.write_u64::<LittleEndian>(from_services.0)?;
|
writer.write_u64::<LittleEndian>(from_services.bits())?;
|
||||||
writer.write_socket_addr(*from_addr)?;
|
writer.write_socket_addr(*from_addr)?;
|
||||||
|
|
||||||
writer.write_u64::<LittleEndian>(nonce.0)?;
|
writer.write_u64::<LittleEndian>(nonce.0)?;
|
||||||
|
|
@ -341,14 +341,15 @@ impl Codec {
|
||||||
fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
|
fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
|
||||||
Ok(Message::Version {
|
Ok(Message::Version {
|
||||||
version: Version(reader.read_u32::<LittleEndian>()?),
|
version: Version(reader.read_u32::<LittleEndian>()?),
|
||||||
services: PeerServices(reader.read_u64::<LittleEndian>()?),
|
// Use from_bits_truncate to discard unknown service bits.
|
||||||
|
services: PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
|
||||||
timestamp: Utc.timestamp(reader.read_i64::<LittleEndian>()?, 0),
|
timestamp: Utc.timestamp(reader.read_i64::<LittleEndian>()?, 0),
|
||||||
address_recv: (
|
address_recv: (
|
||||||
PeerServices(reader.read_u64::<LittleEndian>()?),
|
PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
|
||||||
reader.read_socket_addr()?,
|
reader.read_socket_addr()?,
|
||||||
),
|
),
|
||||||
address_from: (
|
address_from: (
|
||||||
PeerServices(reader.read_u64::<LittleEndian>()?),
|
PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
|
||||||
reader.read_socket_addr()?,
|
reader.read_socket_addr()?,
|
||||||
),
|
),
|
||||||
nonce: Nonce(reader.read_u64::<LittleEndian>()?),
|
nonce: Nonce(reader.read_u64::<LittleEndian>()?),
|
||||||
|
|
@ -505,7 +506,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn version_message_round_trip() {
|
fn version_message_round_trip() {
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
let services = PeerServices(0x1);
|
let services = PeerServices::NODE_NETWORK;
|
||||||
let timestamp = Utc.timestamp(1568000000, 0);
|
let timestamp = Utc.timestamp(1568000000, 0);
|
||||||
|
|
||||||
let rt = Runtime::new().unwrap();
|
let rt = Runtime::new().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,21 @@ pub struct Magic(pub [u8; 4]);
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Version(pub u32);
|
pub struct Version(pub u32);
|
||||||
|
|
||||||
/// Bitfield of features to be enabled for this connection.
|
bitflags! {
|
||||||
// Tower provides utilities for service discovery, so this might go
|
/// A bitflag describing services advertised by a node in the network.
|
||||||
// away in the future in favor of that.
|
///
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
/// Note that bits 24-31 are reserved for temporary experiments; other
|
||||||
pub struct PeerServices(pub u64);
|
/// service bits should be allocated via the ZIP process.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct PeerServices: u64 {
|
||||||
|
/// NODE_NETWORK means that the node is a full node capable of serving
|
||||||
|
/// blocks, as opposed to a light client that makes network requests but
|
||||||
|
/// does not provide network services.
|
||||||
|
const NODE_NETWORK = (1 << 0);
|
||||||
|
/// NODE_BLOOM means that the node supports bloom-filtered connections.
|
||||||
|
const NODE_BLOOM = (1 << 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A nonce used in the networking layer to identify messages.
|
/// A nonce used in the networking layer to identify messages.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,16 @@ impl ConnectCmd {
|
||||||
|
|
||||||
let version = Message::Version {
|
let version = Message::Version {
|
||||||
version: constants::CURRENT_VERSION,
|
version: constants::CURRENT_VERSION,
|
||||||
services: PeerServices(1),
|
services: PeerServices::NODE_NETWORK,
|
||||||
timestamp: Utc::now(),
|
timestamp: Utc::now(),
|
||||||
address_recv: (PeerServices(1), self.addr),
|
address_recv: (PeerServices::NODE_NETWORK, self.addr),
|
||||||
// We just make something up because at this stage the `connect` command
|
// We just make something up because at this stage the `connect` command
|
||||||
// doesn't run a server or anything -- will the zcashd respond on the
|
// doesn't run a server or anything -- will the zcashd respond on the
|
||||||
// same tcp connection or try to open one to the bogus address below?
|
// same tcp connection or try to open one to the bogus address below?
|
||||||
address_from: (PeerServices(1), "127.0.0.1:9000".parse().unwrap()),
|
address_from: (
|
||||||
|
PeerServices::NODE_NETWORK,
|
||||||
|
"127.0.0.1:9000".parse().unwrap(),
|
||||||
|
),
|
||||||
nonce: Nonce(1),
|
nonce: Nonce(1),
|
||||||
user_agent: "Zebra Connect".to_owned(),
|
user_agent: "Zebra Connect".to_owned(),
|
||||||
start_height: BlockHeight(0),
|
start_height: BlockHeight(0),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue