Replace PeerServices(u64) with a bitflags struct.

This gives considerably better ergonomics.
This commit is contained in:
Henry de Valence 2019-09-30 11:58:32 -07:00 committed by Deirdre Connolly
parent 9603a29399
commit f5dca597dd
6 changed files with 35 additions and 17 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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()?,
}) })
} }

View File

@ -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();

View File

@ -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)]

View File

@ -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),