diff --git a/zebra-network/src/protocol/codec.rs b/zebra-network/src/protocol/codec.rs index 52f98d5d..e5230174 100644 --- a/zebra-network/src/protocol/codec.rs +++ b/zebra-network/src/protocol/codec.rs @@ -19,7 +19,7 @@ use zebra_chain::{ use crate::{constants, types::Network}; -use super::{inv::InventoryHash, message::Message, types::*}; +use super::{inv::InventoryHash, message::{Message, RejectReason}, types::*}; /// The length of a Bitcoin message header. const HEADER_LEN: usize = 24usize; @@ -188,7 +188,17 @@ impl Codec { Pong(nonce) => { writer.write_u64::(nonce.0)?; } - // Reject {} => {} + Reject { + ref message, + ref ccode, + ref reason, + ref data, + } => { + writer.write_string(&message)?; + writer.write_u8(*ccode as u8)?; + writer.write_string(&reason)?; + writer.write_all(&data.unwrap())?; + } Addr(ref addrs) => { writer.write_compactsize(addrs.len() as u64)?; for addr in addrs { @@ -254,7 +264,7 @@ impl Codec { Tx { ref version, ref transaction, - } => { + } => { writer.write_u32::(version.0)?; transaction.zcash_serialize(&mut writer)? } @@ -446,8 +456,23 @@ impl Codec { Ok(Message::Pong(Nonce(reader.read_u64::()?))) } - fn read_reject(&self, mut _reader: R) -> Result { - return Err(Error::Parse("reject messages are not implemented")); + fn read_reject(&self, mut reader: R) -> Result { + Ok(Message::Reject { + message: reader.read_string()?, + ccode: match reader.read_u8()? { + 0x01 => RejectReason::Malformed, + 0x10 => RejectReason::Invalid, + 0x11 => RejectReason::Obsolete, + 0x12 => RejectReason::Duplicate, + 0x40 => RejectReason::Nonstandard, + 0x41 => RejectReason::Dust, + 0x42 => RejectReason::InsufficientFee, + 0x43 => RejectReason::Checkpoint, + _ => return Err(Error::Parse("invalid RejectReason value in ccode field")), + }, + reason: reader.read_string()?, + data: Some(reader.read_32_bytes()?) + }) } fn read_addr(&self, mut reader: R) -> Result { diff --git a/zebra-network/src/protocol/message.rs b/zebra-network/src/protocol/message.rs index a391e04d..4525388b 100644 --- a/zebra-network/src/protocol/message.rs +++ b/zebra-network/src/protocol/message.rs @@ -105,8 +105,9 @@ pub enum Message { /// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#reject) Reject { /// Type of message rejected. - // Q: can we just reference the Type, rather than instantiate an instance of the enum type? - message: Box, + // It's unclear if this is strictly limited to message command + // codes, so leaving it a String. + message: String, /// RejectReason code relating to rejected message. ccode: RejectReason,