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
[dependencies]
bitflags = "1.2"
bytes = "0.4"
rand = "0.7"
byteorder = "1.3"

View File

@ -6,6 +6,8 @@
extern crate failure;
#[macro_use]
extern crate tracing;
#[macro_use]
extern crate bitflags;
mod network;
pub use network::Network;

View File

@ -31,7 +31,7 @@ pub struct MetaAddr {
impl ZcashSerialize for MetaAddr {
fn zcash_serialize<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
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)?;
Ok(())
}
@ -41,7 +41,8 @@ impl ZcashDeserialize for MetaAddr {
fn zcash_deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
Ok(MetaAddr {
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()?,
})
}

View File

@ -174,15 +174,15 @@ impl Codec {
ref relay,
} => {
writer.write_u32::<LittleEndian>(version.0)?;
writer.write_u64::<LittleEndian>(services.0)?;
writer.write_u64::<LittleEndian>(services.bits())?;
writer.write_i64::<LittleEndian>(timestamp.timestamp())?;
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)?;
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_u64::<LittleEndian>(nonce.0)?;
@ -341,14 +341,15 @@ impl Codec {
fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
Ok(Message::Version {
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),
address_recv: (
PeerServices(reader.read_u64::<LittleEndian>()?),
PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
reader.read_socket_addr()?,
),
address_from: (
PeerServices(reader.read_u64::<LittleEndian>()?),
PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
reader.read_socket_addr()?,
),
nonce: Nonce(reader.read_u64::<LittleEndian>()?),
@ -505,7 +506,7 @@ mod tests {
#[test]
fn version_message_round_trip() {
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
let services = PeerServices(0x1);
let services = PeerServices::NODE_NETWORK;
let timestamp = Utc.timestamp(1568000000, 0);
let rt = Runtime::new().unwrap();

View File

@ -8,11 +8,21 @@ pub struct Magic(pub [u8; 4]);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Version(pub u32);
/// Bitfield of features to be enabled for this connection.
// Tower provides utilities for service discovery, so this might go
// away in the future in favor of that.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PeerServices(pub u64);
bitflags! {
/// A bitflag describing services advertised by a node in the network.
///
/// Note that bits 24-31 are reserved for temporary experiments; other
/// 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.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]

View File

@ -70,13 +70,16 @@ impl ConnectCmd {
let version = Message::Version {
version: constants::CURRENT_VERSION,
services: PeerServices(1),
services: PeerServices::NODE_NETWORK,
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
// 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?
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),
user_agent: "Zebra Connect".to_owned(),
start_height: BlockHeight(0),