diff --git a/crates/common/rlp/src/decode.rs b/crates/common/rlp/src/decode.rs index 75bca59304..fa68dc7416 100644 --- a/crates/common/rlp/src/decode.rs +++ b/crates/common/rlp/src/decode.rs @@ -218,6 +218,33 @@ impl Decodable for bool { } } +#[cfg(feature = "std")] +impl Decodable for std::net::IpAddr { + fn decode(buf: &mut &[u8]) -> Result { + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + + let h = Header::decode(buf)?; + if h.list { + return Err(DecodeError::UnexpectedList) + } + let o = match h.payload_length { + 4 => { + let mut to = [0_u8; 4]; + to.copy_from_slice(&buf[..4]); + IpAddr::V4(Ipv4Addr::from(to)) + } + 16 => { + let mut to = [0u8; 16]; + to.copy_from_slice(&buf[..16]); + IpAddr::V6(Ipv6Addr::from(to)) + } + _ => return Err(DecodeError::UnexpectedLength), + }; + buf.advance(h.payload_length); + Ok(o) + } +} + #[cfg(feature = "ethnum")] decode_integer!(ethnum::U256); diff --git a/crates/common/rlp/src/encode.rs b/crates/common/rlp/src/encode.rs index d78ff42226..46fa80140b 100644 --- a/crates/common/rlp/src/encode.rs +++ b/crates/common/rlp/src/encode.rs @@ -217,6 +217,16 @@ where } } +#[cfg(feature = "std")] +impl Encodable for std::net::IpAddr { + fn encode(&self, out: &mut dyn BufMut) { + match self { + std::net::IpAddr::V4(ref o) => (&o.octets()[..]).encode(out), + std::net::IpAddr::V6(ref o) => (&o.octets()[..]).encode(out), + } + } +} + #[cfg(feature = "ethnum")] mod ethnum_support { use super::*; diff --git a/crates/net/discv4/src/proto.rs b/crates/net/discv4/src/proto.rs index 734d4470fe..e999093417 100644 --- a/crates/net/discv4/src/proto.rs +++ b/crates/net/discv4/src/proto.rs @@ -3,7 +3,7 @@ use crate::{error::DecodePacketError, PeerId, MAX_PACKET_SIZE, MIN_PACKET_SIZE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use enr::Enr; -use reth_primitives::{keccak256, ForkId, NodeRecord, Octets, H256}; +use reth_primitives::{keccak256, ForkId, NodeRecord, H256}; use reth_rlp::{Decodable, DecodeError, Encodable, Header}; use reth_rlp_derive::{RlpDecodable, RlpEncodable}; use secp256k1::{ @@ -180,58 +180,12 @@ pub struct Packet { } /// Represents the `from`, `to` fields in the packets -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)] pub struct NodeEndpoint { pub address: IpAddr, pub udp_port: u16, pub tcp_port: u16, } -impl Decodable for NodeEndpoint { - fn decode(buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = Header::decode(b)?; - if !rlp_head.list { - return Err(DecodeError::UnexpectedString) - } - let started_len = b.len(); - let octets = Octets::decode(b)?; - let this = Self { - address: octets.into(), - udp_port: Decodable::decode(b)?, - tcp_port: Decodable::decode(b)?, - }; - // the ENR record can contain additional entries that we skip - let consumed = started_len - b.len(); - if consumed > rlp_head.payload_length { - return Err(DecodeError::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }) - } - let rem = rlp_head.payload_length - consumed; - b.advance(rem); - *buf = *b; - Ok(this) - } -} - -impl Encodable for NodeEndpoint { - fn encode(&self, out: &mut dyn BufMut) { - #[derive(RlpEncodable)] - struct RlpEndpoint { - octets: Octets, - udp_port: u16, - tcp_port: u16, - } - - let octets = match self.address { - IpAddr::V4(addr) => Octets::V4(addr.octets()), - IpAddr::V6(addr) => Octets::V6(addr.octets()), - }; - let p = RlpEndpoint { octets, udp_port: self.udp_port, tcp_port: self.tcp_port }; - p.encode(out) - } -} impl From for NodeEndpoint { fn from(NodeRecord { address, tcp_port, udp_port, .. }: NodeRecord) -> Self { diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index ea089e490e..0a6369fb4b 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -43,7 +43,7 @@ pub use hex_bytes::Bytes; pub use integer_list::IntegerList; pub use jsonu256::JsonU256; pub use log::Log; -pub use net::{NodeRecord, Octets}; +pub use net::NodeRecord; pub use peer::{PeerId, WithPeerId}; pub use receipt::Receipt; pub use storage::StorageEntry; diff --git a/crates/primitives/src/net.rs b/crates/primitives/src/net.rs index cf9e62eb1f..d2c9322b48 100644 --- a/crates/primitives/src/net.rs +++ b/crates/primitives/src/net.rs @@ -1,13 +1,12 @@ use crate::PeerId; -use bytes::{Buf, BufMut}; -use reth_rlp::{Decodable, DecodeError, Encodable, Header}; +use reth_rlp::RlpDecodable; use reth_rlp_derive::RlpEncodable; use secp256k1::{SecretKey, SECP256K1}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use std::{ fmt, fmt::Write, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + net::{IpAddr, Ipv4Addr, SocketAddr}, num::ParseIntError, str::FromStr, }; @@ -17,7 +16,18 @@ use url::{Host, Url}; /// /// Note: this is only an excerpt of the [ENR](enr::Enr) datastructure which is sent in Neighbours /// message. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, SerializeDisplay, DeserializeFromStr)] +#[derive( + Clone, + Copy, + Debug, + Eq, + PartialEq, + Hash, + SerializeDisplay, + DeserializeFromStr, + RlpEncodable, + RlpDecodable, +)] pub struct NodeRecord { /// The Address of a node. pub address: IpAddr, @@ -125,121 +135,12 @@ impl FromStr for NodeRecord { } } -impl Encodable for NodeRecord { - fn encode(&self, out: &mut dyn BufMut) { - #[derive(RlpEncodable)] - struct EncodeNode { - octets: Octets, - udp_port: u16, - tcp_port: u16, - id: PeerId, - } - - let octets = match self.address { - IpAddr::V4(addr) => Octets::V4(addr.octets()), - IpAddr::V6(addr) => Octets::V6(addr.octets()), - }; - let node = - EncodeNode { octets, udp_port: self.udp_port, tcp_port: self.tcp_port, id: self.id }; - node.encode(out) - } -} - -impl Decodable for NodeRecord { - fn decode(buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = reth_rlp::Header::decode(b)?; - if !rlp_head.list { - return Err(DecodeError::UnexpectedString) - } - let started_len = b.len(); - let octets = Octets::decode(b)?; - let this = Self { - address: octets.into(), - udp_port: Decodable::decode(b)?, - tcp_port: Decodable::decode(b)?, - id: Decodable::decode(b)?, - }; - // the ENR record can contain additional entries that we skip - let consumed = started_len - b.len(); - if consumed > rlp_head.payload_length { - return Err(DecodeError::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }) - } - let rem = rlp_head.payload_length - consumed; - b.advance(rem); - *buf = *b; - Ok(this) - } -} - -/// IpAddr octets -#[derive(Debug, Copy, Clone)] -pub enum Octets { - /// Ipv4 Octet variant - V4([u8; 4]), - /// Ipv6 Octet variant - V6([u8; 16]), -} - -impl From for IpAddr { - fn from(value: Octets) -> Self { - match value { - Octets::V4(o) => IpAddr::from(o), - Octets::V6(o) => { - let ipv6 = Ipv6Addr::from(o); - // If the ipv6 is ipv4 compatible/mapped, simply return the ipv4. - if let Some(ipv4) = ipv6.to_ipv4() { - IpAddr::V4(ipv4) - } else { - IpAddr::V6(ipv6) - } - } - } - } -} - -impl Encodable for Octets { - fn encode(&self, out: &mut dyn BufMut) { - let octets = match self { - Octets::V4(ref o) => &o[..], - Octets::V6(ref o) => &o[..], - }; - octets.encode(out) - } -} - -impl Decodable for Octets { - fn decode(buf: &mut &[u8]) -> Result { - let h = Header::decode(buf)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - let o = match h.payload_length { - 4 => { - let mut to = [0_u8; 4]; - to.copy_from_slice(&buf[..4]); - Octets::V4(to) - } - 16 => { - let mut to = [0u8; 16]; - to.copy_from_slice(&buf[..16]); - Octets::V6(to) - } - _ => return Err(DecodeError::UnexpectedLength), - }; - buf.advance(h.payload_length); - Ok(o) - } -} - #[cfg(test)] mod tests { use super::*; use bytes::BytesMut; use rand::{thread_rng, Rng, RngCore}; + use reth_rlp::{Decodable, Encodable}; #[test] fn test_noderecord_codec_ipv4() {