Add addr, getaddr serialization.
This commit is contained in:
parent
9f43d0987b
commit
0a85be285d
|
@ -1,8 +1,15 @@
|
||||||
//! An address-with-metadata type used in Bitcoin networking.
|
//! An address-with-metadata type used in Bitcoin networking.
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use std::io::{Read, Write};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use chrono::{DateTime, TimeZone, Utc};
|
||||||
|
|
||||||
|
use zebra_chain::serialization::{
|
||||||
|
ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::protocol::types::Services;
|
use crate::protocol::types::Services;
|
||||||
|
|
||||||
/// An address with metadata on its advertised services and last-seen time.
|
/// An address with metadata on its advertised services and last-seen time.
|
||||||
|
@ -20,3 +27,22 @@ pub struct MetaAddr {
|
||||||
/// When the peer was last seen.
|
/// When the peer was last seen.
|
||||||
pub last_seen: DateTime<Utc>,
|
pub last_seen: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_socket_addr(self.addr)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: Services(reader.read_u64::<LittleEndian>()?),
|
||||||
|
addr: reader.read_socket_addr()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -197,6 +197,13 @@ impl Codec {
|
||||||
Pong(nonce) => {
|
Pong(nonce) => {
|
||||||
writer.write_u64::<LittleEndian>(nonce.0)?;
|
writer.write_u64::<LittleEndian>(nonce.0)?;
|
||||||
}
|
}
|
||||||
|
GetAddr => { /* Empty payload -- no-op */ }
|
||||||
|
Addr(ref addrs) => {
|
||||||
|
writer.write_compactsize(addrs.len() as u64)?;
|
||||||
|
for addr in addrs {
|
||||||
|
addr.zcash_serialize(&mut writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
Inv(ref hashes) => {
|
Inv(ref hashes) => {
|
||||||
writer.write_compactsize(hashes.len() as u64)?;
|
writer.write_compactsize(hashes.len() as u64)?;
|
||||||
for hash in hashes {
|
for hash in hashes {
|
||||||
|
@ -372,9 +379,31 @@ impl Codec {
|
||||||
bail!("unimplemented message type")
|
bail!("unimplemented message type")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_addr<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
|
fn read_addr<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
|
||||||
trace!("addr");
|
use crate::meta_addr::MetaAddr;
|
||||||
bail!("unimplemented message type")
|
|
||||||
|
// XXX we may want to factor this logic out into
|
||||||
|
// fn read_vec<R: Read, T: ZcashDeserialize>(reader: R) -> Result<Vec<T>, Error>
|
||||||
|
// on ReadZcashExt (and similarly for WriteZcashExt)
|
||||||
|
let count = reader.read_compactsize()? as usize;
|
||||||
|
// Preallocate a buffer, performing a single allocation in the honest
|
||||||
|
// case. Although the size of the recieved data buffer is bounded by the
|
||||||
|
// codec's max_len field, it's still possible for someone to send a
|
||||||
|
// short addr message with a large count field, so if we naively trust
|
||||||
|
// the count field we could be tricked into preallocating a large
|
||||||
|
// buffer. Instead, calculate the maximum count for a valid message from
|
||||||
|
// the codec's max_len using ENCODED_ADDR_SIZE.
|
||||||
|
//
|
||||||
|
// addrs are encoded as: timestamp + services + ipv6 + port
|
||||||
|
const ENCODED_ADDR_SIZE: usize = 4 + 8 + 16 + 2;
|
||||||
|
let max_count = self.builder.max_len / ENCODED_ADDR_SIZE;
|
||||||
|
let mut addrs = Vec::with_capacity(std::cmp::min(count, max_count));
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
addrs.push(MetaAddr::zcash_deserialize(&mut reader)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Message::Addr(addrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_getaddr<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
|
fn read_getaddr<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
|
||||||
|
|
Loading…
Reference in New Issue