From 4d04cc30cda1f669af0179206bc8dc67b4bc5ac1 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Wed, 9 Aug 2023 18:55:09 -0400 Subject: [PATCH 01/19] change rlp to alloy-rlp --- Cargo.toml | 3 +- src/builder.rs | 35 ++++--- src/keys/k256_key.rs | 6 +- src/keys/mod.rs | 2 +- src/lib.rs | 230 +++++++++++++++---------------------------- 5 files changed, 109 insertions(+), 167 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9be0141..147ba98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,13 @@ license = "MIT" exclude = [".gitignore", ".github/*"] [dependencies] +alloy-rlp = { version = "0.3.2", default-features = false } +alloy-rlp-derive = { version = "0.3.2", default-features = false } base64 = "0.21.0" bytes = "1" hex = {version = "0.4.2"} log = "0.4.8" rand = "0.8" -rlp = "0.5" zeroize = "1.1.0" sha3 = "0.10" k256 = { version = "0.13", features = ["ecdsa"], optional = true } diff --git a/src/builder.rs b/src/builder.rs index 0ec0b3d..c7503ad 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,6 +1,6 @@ -use crate::{Enr, EnrError, EnrKey, EnrPublicKey, Key, NodeId, MAX_ENR_SIZE}; +use crate::{encoded_list, Enr, EnrError, EnrKey, EnrPublicKey, Key, NodeId, MAX_ENR_SIZE}; +use alloy_rlp::{Decodable, Encodable}; use bytes::{Bytes, BytesMut}; -use rlp::{Encodable, RlpStream}; use std::{ collections::BTreeMap, marker::PhantomData, @@ -44,7 +44,10 @@ impl EnrBuilder { /// Adds an arbitrary key-value to the `ENRBuilder`. pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: &T) -> &mut Self { - self.add_value_rlp(key, rlp::encode(value).freeze()) + self.add_value_rlp( + key, + Bytes::copy_from_slice(alloy_rlp::encode(value).as_slice()), + ) } /// Adds an arbitrary key-value where the value is raw RLP encoded bytes. @@ -110,15 +113,15 @@ impl EnrBuilder { /// Generates the rlp-encoded form of the ENR specified by the builder config. fn rlp_content(&self) -> BytesMut { - let mut stream = RlpStream::new_with_buffer(BytesMut::with_capacity(MAX_ENR_SIZE)); - stream.begin_list(self.content.len() * 2 + 1); - stream.append(&self.seq); + let mut list = Vec::::with_capacity(MAX_ENR_SIZE); + list.append(&mut self.seq.to_ne_bytes().to_vec()); for (k, v) in &self.content { - stream.append(k); - // The values are stored as raw RLP encoded bytes - stream.append_raw(v, 1); + // Keys are bytes + list.append(&mut k.as_slice().to_vec()); + // Values are raw RLP encoded data + list.append(&mut v.to_vec()); } - stream.out() + encoded_list(&list) } /// Signs record based on the identity scheme. Currently only "v4" is supported. @@ -149,14 +152,22 @@ impl EnrBuilder { // Sanitize all data, ensuring all RLP data is correctly formatted. for (key, value) in &self.content { - if rlp::Rlp::new(value).data().is_err() { + if Vec::::decode(&mut key.as_slice()).is_err() { return Err(EnrError::InvalidRlpData( String::from_utf8_lossy(key).into(), )); } + if Vec::::decode(&mut value.to_vec().as_slice()).is_err() { + return Err(EnrError::InvalidRlpData( + String::from_utf8_lossy(value).into(), + )); + } } - self.add_value_rlp("id", rlp::encode(&self.id.as_bytes()).freeze()); + self.add_value_rlp( + "id", + Bytes::copy_from_slice(alloy_rlp::encode(self.id.as_bytes()).as_slice()), + ); self.add_public_key(&key.public()); let rlp_content = self.rlp_content(); diff --git a/src/keys/k256_key.rs b/src/keys/k256_key.rs index dbfa3e4..ad6c675 100644 --- a/src/keys/k256_key.rs +++ b/src/keys/k256_key.rs @@ -2,6 +2,7 @@ use super::{EnrKey, EnrKeyUnambiguous, EnrPublicKey, SigningError}; use crate::Key; +use alloy_rlp::{Decodable, Error as DecoderError}; use bytes::Bytes; use k256::{ ecdsa::{ @@ -16,7 +17,6 @@ use k256::{ AffinePoint, CompressedPoint, EncodedPoint, }; use rand::rngs::OsRng; -use rlp::DecoderError; use sha3::{Digest, Keccak256}; use std::{collections::BTreeMap, convert::TryFrom}; @@ -46,9 +46,9 @@ impl EnrKey for SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?; + let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes) + Self::decode_public(pubkey_bytes.as_slice()) } } diff --git a/src/keys/mod.rs b/src/keys/mod.rs index 6d3b986..0c26b37 100644 --- a/src/keys/mod.rs +++ b/src/keys/mod.rs @@ -24,8 +24,8 @@ pub use k256; pub use secp256k1; use crate::Key; +use alloy_rlp::Error as DecoderError; use bytes::Bytes; -use rlp::DecoderError; use std::{ collections::BTreeMap, error::Error, diff --git a/src/lib.rs b/src/lib.rs index 88bf1cf..ef3ed6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,10 +181,8 @@ mod builder; mod error; mod keys; mod node_id; - +use alloy_rlp::{Decodable, Encodable, Error as DecoderError}; use bytes::{Bytes, BytesMut}; -use log::debug; -use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; use std::{ collections::BTreeMap, hash::{Hash, Hasher}, @@ -260,11 +258,7 @@ impl Enr { /// Reads a custom key from the record if it exists, decoded as data. pub fn get(&self, key: impl AsRef<[u8]>) -> Option<&[u8]> { // It's ok to decode any valid RLP value as data - self.get_raw_rlp(key).map(|rlp_data| { - rlp::Rlp::new(rlp_data) - .data() - .expect("All data is sanitized") - }) + self.get_raw_rlp(key) } /// Reads a custom key from the record if it exists, decoded as `T`. @@ -272,7 +266,8 @@ impl Enr { &self, key: impl AsRef<[u8]>, ) -> Option> { - self.get_raw_rlp(key).map(|rlp_data| rlp::decode(rlp_data)) + self.get_raw_rlp(key) + .map(|mut rlp_data| Decodable::decode(&mut rlp_data)) } /// Reads a custom key from the record if it exists as raw RLP bytes. @@ -420,14 +415,14 @@ impl Enr { /// Provides the URL-safe base64 encoded "text" version of the ENR prefixed by "enr:". #[must_use] pub fn to_base64(&self) -> String { - let hex = URL_SAFE_NO_PAD.encode(&rlp::encode(self)); + let hex = URL_SAFE_NO_PAD.encode(alloy_rlp::encode(self)); format!("enr:{hex}") } /// Returns the current size of the ENR. #[must_use] pub fn size(&self) -> usize { - rlp::encode(self).len() + alloy_rlp::encode(self).len() } // Setters // @@ -460,7 +455,11 @@ impl Enr { value: &T, enr_key: &K, ) -> Result, EnrError> { - self.insert_raw_rlp(key, rlp::encode(value).freeze(), enr_key) + self.insert_raw_rlp( + key, + Bytes::copy_from_slice(alloy_rlp::encode(value).as_slice()), + enr_key, + ) } /// Adds or modifies a key/value to the ENR record. A `EnrKey` is required to re-sign the record once @@ -480,7 +479,7 @@ impl Enr { let public_key = enr_key.public(); let previous_key = self.content.insert( public_key.enr_key(), - rlp::encode(&public_key.encode().as_ref()).freeze(), + Bytes::copy_from_slice(alloy_rlp::encode(public_key.encode().as_ref()).as_slice()), ); // check the size of the record @@ -551,7 +550,7 @@ impl Enr { /// Sets the `udp` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp4(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp", &udp, key)? { - return Ok(rlp::decode(&udp_bytes).ok()); + return Ok(Decodable::decode(&mut udp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -559,7 +558,7 @@ impl Enr { /// Sets the `udp6` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp6(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp6", &udp, key)? { - return Ok(rlp::decode(&udp_bytes).ok()); + return Ok(Decodable::decode(&mut udp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -567,7 +566,7 @@ impl Enr { /// Sets the `tcp` field of the ENR. Returns any pre-existing tcp port in the record. pub fn set_tcp4(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp", &tcp, key)? { - return Ok(rlp::decode(&tcp_bytes).ok()); + return Ok(Decodable::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -575,7 +574,7 @@ impl Enr { /// Sets the `tcp6` field of the ENR. Returns any pre-existing tcp6 port in the record. pub fn set_tcp6(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp6", &tcp, key)? { - return Ok(rlp::decode(&tcp_bytes).ok()); + return Ok(Decodable::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -602,25 +601,29 @@ impl Enr { IpAddr::V4(addr) => ( self.content.insert( "ip".into(), - rlp::encode(&(&addr.octets() as &[u8])).freeze(), + Bytes::copy_from_slice(&alloy_rlp::encode(addr.octets().to_vec())), + ), + self.content.insert( + port_string.clone(), + Bytes::copy_from_slice(&alloy_rlp::encode(socket.port())), ), - self.content - .insert(port_string.clone(), rlp::encode(&socket.port()).freeze()), ), IpAddr::V6(addr) => ( self.content.insert( "ip6".into(), - rlp::encode(&(&addr.octets() as &[u8])).freeze(), + Bytes::copy_from_slice(&alloy_rlp::encode(addr.octets().to_vec())), + ), + self.content.insert( + port_v6_string.clone(), + Bytes::copy_from_slice(&alloy_rlp::encode(socket.port())), ), - self.content - .insert(port_v6_string.clone(), rlp::encode(&socket.port()).freeze()), ), }; let public_key = key.public(); let previous_key = self.content.insert( public_key.enr_key(), - rlp::encode(&public_key.encode().as_ref()).freeze(), + Bytes::copy_from_slice(&alloy_rlp::encode(public_key.encode().as_ref())), ); // check the size and revert on failure @@ -700,7 +703,7 @@ impl Enr { let public_key = enr_key.public(); self.content.insert( public_key.enr_key(), - rlp::encode(&public_key.encode().as_ref()).freeze(), + Bytes::copy_from_slice(&alloy_rlp::encode(public_key.encode().as_ref())), ); let mut inserted = Vec::new(); @@ -711,10 +714,10 @@ impl Enr { return Err(EnrError::UnsupportedIdentityScheme); } - let value = rlp::encode(&(value)).freeze(); + let value = Bytes::copy_from_slice(&alloy_rlp::encode(value)); // Prevent inserting invalid RLP integers if is_keyof_u16(key.as_ref()) { - rlp::decode::(&value) + ::decode(&mut value.to_vec().as_slice()) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } @@ -765,16 +768,15 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { - let mut stream = RlpStream::new_with_buffer(BytesMut::with_capacity(MAX_ENR_SIZE)); - stream.begin_list(self.content.len() * 2 + 1); - stream.append(&self.seq); + let mut list = Vec::::with_capacity(MAX_ENR_SIZE); + list.append(&mut self.seq.to_ne_bytes().to_vec()); for (k, v) in &self.content { // Keys are bytes - stream.append(k); + list.append(&mut k.as_slice().to_vec()); // Values are raw RLP encoded data - stream.append_raw(v, 1); + list.append(&mut v.to_vec()); } - stream.out() + encoded_list(&list) } /// Signs the ENR record based on the identity scheme. Currently only "v4" is supported. @@ -887,7 +889,7 @@ impl FromStr for Enr { if bytes.len() > MAX_ENR_SIZE { return Err("enr exceeds max size".to_string()); } - rlp::decode(&bytes).map_err(|e| format!("Invalid ENR: {e:?}")) + Decodable::decode(&mut bytes.as_slice()).map_err(|e| format!("Invalid ENR: {e:?}")) } } @@ -912,94 +914,15 @@ impl<'de, K: EnrKey> Deserialize<'de> for Enr { } } -impl rlp::Encodable for Enr { - fn rlp_append(&self, s: &mut RlpStream) { - s.begin_list(self.content.len() * 2 + 2); - s.append(&self.signature); - s.append(&self.seq); - // must use rlp_content to preserve ordering. - for (k, v) in &self.content { - // Keys are byte data - s.append(k); - // Values are raw RLP encoded data - s.append_raw(v, 1); - } +impl Encodable for Enr { + fn encode(&self, _out: &mut dyn bytes::BufMut) { + todo!() } } -impl rlp::Decodable for Enr { - fn decode(rlp: &Rlp) -> Result { - if !rlp.is_list() { - debug!("Failed to decode ENR. Not an RLP list: {}", rlp); - return Err(DecoderError::RlpExpectedToBeList); - } - - // verify there is no extra data - let payload_info = rlp.payload_info()?; - if rlp.as_raw().len() != payload_info.header_len + payload_info.value_len { - return Err(DecoderError::RlpInconsistentLengthAndData); - } - - let mut rlp_iter = rlp.iter(); - - if rlp_iter.len() == 0 || rlp_iter.len() % 2 != 0 { - debug!("Failed to decode ENR. List size is not a multiple of 2."); - return Err(DecoderError::Custom("List not a multiple of two")); - } - - let signature = rlp_iter - .next() - .ok_or(DecoderError::Custom("List is empty"))? - .data()?; - let seq = rlp_iter - .next() - .ok_or(DecoderError::Custom("List has only one item"))? - .as_val()?; - - let mut content = BTreeMap::new(); - let mut prev: Option<&[u8]> = None; - while let Some(key) = rlp_iter.next() { - let key = key.data()?; - let item = rlp_iter - .next() - .ok_or(DecoderError::Custom("List not a multiple of 2"))?; - - // Sanitize the data - if is_keyof_u16(key) { - item.as_val::()?; - } else { - item.data()?; - } - let value = item.as_raw(); - - if prev.is_some() && prev >= Some(key) { - return Err(DecoderError::Custom("Unsorted keys")); - } - prev = Some(key); - content.insert(key.to_vec(), Bytes::copy_from_slice(value)); - } - - // verify we know the signature type - let public_key = K::enr_to_public(&content)?; - - // calculate the node id - let node_id = NodeId::from(public_key); - - let enr = Self { - seq, - node_id, - signature: signature.into(), - content, - phantom: PhantomData, - }; - - // verify the signature before returning - // if the public key is of an unknown type, this will fail. - // An ENR record will always have a valid public-key and therefore node-id - if !enr.verify() { - return Err(DecoderError::Custom("Invalid Signature")); - } - Ok(enr) +impl Decodable for Enr { + fn decode(_buf: &mut &[u8]) -> Result { + todo!() } } @@ -1038,34 +961,34 @@ const fn is_keyof_u16(key: &[u8]) -> bool { matches!(key, b"tcp" | b"tcp6" | b"udp" | b"udp6") } -fn check_spec_reserved_keys(key: &[u8], value: &[u8]) -> Result<(), EnrError> { +fn check_spec_reserved_keys(key: &[u8], mut value: &[u8]) -> Result<(), EnrError> { match key { b"tcp" | b"tcp6" | b"udp" | b"udp6" => { - rlp::decode::(value).map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; + u16::decode(&mut value).map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } b"id" => { - let id_bytes = rlp::decode::>(value) + let id_bytes = Vec::::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; if id_bytes != b"v4" { return Err(EnrError::UnsupportedIdentityScheme); } } b"ip" => { - let ip4_bytes = rlp::decode::>(value) + let ip4_bytes = Vec::::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; if ip4_bytes.len() != 4 { return Err(EnrError::InvalidRlpData("Invalid Ipv4 size".to_string())); } } b"ip6" => { - let ip6_bytes = rlp::decode::>(value) + let ip6_bytes = Vec::::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; if ip6_bytes.len() != 16 { return Err(EnrError::InvalidRlpData("Invalid Ipv6 size".to_string())); } } b"secp256k1" => { - rlp::decode::>(value) + >::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } _ => return Ok(()), @@ -1073,6 +996,12 @@ fn check_spec_reserved_keys(key: &[u8], value: &[u8]) -> Result<(), EnrError> { Ok(()) } +pub fn encoded_list(t: &[T]) -> BytesMut { + let mut out = BytesMut::new(); + alloy_rlp::encode_list(t, &mut out); + out +} + #[cfg(test)] #[cfg(feature = "k256")] mod tests { @@ -1091,7 +1020,7 @@ mod tests { hex::decode("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") .unwrap(); - let enr = rlp::decode::(&valid_record).unwrap(); + let enr = ::decode(&mut valid_record.as_slice()).unwrap(); let pubkey = enr.public_key().encode(); @@ -1273,16 +1202,18 @@ mod tests { hex::decode("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") .unwrap(); - let enr = rlp::decode::(&valid_record).unwrap(); + let enr = ::decode(&mut valid_record.as_slice()).unwrap(); let pubkey = enr.public_key().encode(); assert_eq!(pubkey.to_vec(), expected_pubkey); assert!(enr.verify()); let invalid_record = hex::decode(record_hex2).unwrap(); - rlp::decode::(&invalid_record).expect_err("should reject extra data"); + ::decode(&mut invalid_record.as_slice()) + .expect_err("should reject extra data"); let invalid_record = hex::decode(record_hex3).unwrap(); - rlp::decode::(&invalid_record).expect_err("should reject extra data"); + ::decode(&mut invalid_record.as_slice()) + .expect_err("should reject extra data"); } /// Tests that RLP integers decoding rejects any item with leading zeroes. @@ -1326,9 +1257,10 @@ mod tests { builder.build(&key).unwrap() }; - let encoded_enr = rlp::encode(&enr); + let mut buffer = Vec::::new(); + let encoded_enr = enr.encode(&mut buffer); - let decoded_enr = rlp::decode::>(&encoded_enr).unwrap(); + let decoded_enr = Decodable::decode(&mut encoded_enr.as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); @@ -1399,9 +1331,11 @@ mod tests { builder.build(&key).unwrap() }; - let encoded_enr = rlp::encode(&enr); + let mut encoded_enr = Vec::::new(); + enr.encode(&mut encoded_enr); - let decoded_enr = rlp::decode::>(&encoded_enr).unwrap(); + let decoded_enr: Enr = + Enr::decode(&mut encoded_enr.as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); @@ -1427,8 +1361,8 @@ mod tests { builder.build(&key).unwrap() }; - let encoded_enr = rlp::encode(&enr); - let decoded_enr = rlp::decode::>(&encoded_enr).unwrap(); + let encoded_enr = Rlp::encode(&enr); + let decoded_enr = Rlp::decode::>(&encoded_enr).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); @@ -1451,7 +1385,7 @@ mod tests { builder.build(&key).unwrap() }; - enr.insert("random", &Vec::new(), &key).unwrap(); + enr.insert("random", &Vec::::new(), &key).unwrap(); assert!(enr.verify()); } @@ -1550,12 +1484,8 @@ mod tests { let mut rng = rand::thread_rng(); let key = k256::ecdsa::SigningKey::random(&mut rng); let tcp = 30303; - let mut topics = Vec::new(); - let mut s = RlpStream::new(); - s.begin_list(2); - s.append(&"lighthouse"); - s.append(&"eth_syncing"); - topics.extend_from_slice(&s.out().freeze()); + let list = &["lighthouse", "eth_sync"]; + let out = encoded_list(list); let mut enr = { let mut builder = EnrBuilder::new("v4"); @@ -1566,7 +1496,7 @@ mod tests { assert_eq!(enr.tcp4(), Some(tcp)); assert_eq!(enr.get("topics"), None); - let topics: &[u8] = &topics; + let topics: &[u8] = &out; let (removed, inserted) = enr .remove_insert( @@ -1575,11 +1505,9 @@ mod tests { &key, ) .unwrap(); - - assert_eq!( - removed[0], - Some(rlp::encode(&tcp.to_be_bytes().to_vec()).freeze()) - ); + let mut buffer = Vec::::new(); + tcp.encode(&mut buffer); + assert_eq!(removed[0], Some(Bytes::copy_from_slice(&buffer))); assert_eq!(inserted[0], None); assert_eq!(enr.tcp4(), None); @@ -1589,7 +1517,7 @@ mod tests { assert_eq!(enr.public_key().encode(), key.public().encode()); } - /// | n | `rlp::encode(n.to_be_bytes())` | `rlp::encode::(n)` | + /// | n | `Rlp::encode(n.to_be_bytes())` | `Rlp::encode::(n)` | /// | ----- | ------------------------------ | ----------------------- | /// | 0 | 0x820000 | 0x80 /// | 30 | 0x82001e | 0x1e @@ -1697,8 +1625,10 @@ mod tests { } fn assert_tcp4(enr: &DefaultEnr, tcp: u16) { + let mut buffer = Vec::::new(); + tcp.encode(&mut buffer); assert!(enr.verify()); - assert_eq!(enr.get_raw_rlp("tcp").unwrap(), rlp::encode(&tcp).to_vec()); + assert_eq!(enr.get_raw_rlp("tcp").unwrap(), buffer); assert_eq!(enr.tcp4(), Some(tcp)); } } From 06373c5d39098a21ae51ee4319550f0ddf1bd533 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Wed, 9 Aug 2023 19:10:48 -0400 Subject: [PATCH 02/19] clippy --- src/keys/combined.rs | 2 +- src/keys/ed25519.rs | 6 +++--- src/keys/rust_secp256k1.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/keys/combined.rs b/src/keys/combined.rs index 275b6d5..8d858de 100644 --- a/src/keys/combined.rs +++ b/src/keys/combined.rs @@ -4,9 +4,9 @@ //! Currently only `secp256k1` and `ed25519` key types are supported. use super::{ed25519_dalek as ed25519, EnrKey, EnrPublicKey, SigningError}; +use alloy_rlp::Error as DecoderError; use bytes::Bytes; pub use k256; -use rlp::DecoderError; use std::{collections::BTreeMap, convert::TryFrom}; use zeroize::Zeroize; diff --git a/src/keys/ed25519.rs b/src/keys/ed25519.rs index 8f89b8c..8df90aa 100644 --- a/src/keys/ed25519.rs +++ b/src/keys/ed25519.rs @@ -3,8 +3,8 @@ use super::{ EnrKey, EnrKeyUnambiguous, EnrPublicKey, SigningError, }; use crate::Key; +use alloy_rlp::{Decodable, Error as DecoderError}; use bytes::Bytes; -use rlp::DecoderError; use std::{collections::BTreeMap, convert::TryFrom}; /// The ENR key that stores the public key in the ENR record. @@ -33,9 +33,9 @@ impl EnrKey for ed25519::SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?; + let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes) + Self::decode_public(pubkey_bytes.as_slice()) } } diff --git a/src/keys/rust_secp256k1.rs b/src/keys/rust_secp256k1.rs index 93cff1a..456ef3f 100644 --- a/src/keys/rust_secp256k1.rs +++ b/src/keys/rust_secp256k1.rs @@ -1,8 +1,8 @@ use super::{EnrKey, EnrKeyUnambiguous, EnrPublicKey, SigningError}; use crate::{digest, Key}; +use alloy_rlp::{Decodable, Error as DecoderError}; use bytes::Bytes; use rand::RngCore; -use rlp::DecoderError; use secp256k1::SECP256K1; use std::collections::BTreeMap; @@ -40,9 +40,9 @@ impl EnrKey for secp256k1::SecretKey { .get(ENR_KEY.as_bytes()) .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?; + let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes) + Self::decode_public(pubkey_bytes.as_slice()) } } From 2160b4b50e0a63b5ef68c15aec1b3ea3b1342473 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 11 Aug 2023 19:17:21 -0400 Subject: [PATCH 03/19] Working on decode function --- Cargo.toml | 4 +- src/keys/ed25519.rs | 4 +- src/keys/k256_key.rs | 4 +- src/keys/rust_secp256k1.rs | 4 +- src/lib.rs | 148 ++++++++++++++++++++++++++++--------- 5 files changed, 122 insertions(+), 42 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 147ba98..53081c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ license = "MIT" exclude = [".gitignore", ".github/*"] [dependencies] -alloy-rlp = { version = "0.3.2", default-features = false } -alloy-rlp-derive = { version = "0.3.2", default-features = false } +alloy-rlp = { version = "0.3.2", default-features = true } +alloy-rlp-derive = { version = "0.3.2", default-features = true } base64 = "0.21.0" bytes = "1" hex = {version = "0.4.2"} diff --git a/src/keys/ed25519.rs b/src/keys/ed25519.rs index 8df90aa..9780917 100644 --- a/src/keys/ed25519.rs +++ b/src/keys/ed25519.rs @@ -33,9 +33,9 @@ impl EnrKey for ed25519::SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.as_slice()) + Self::decode_public(pubkey_bytes.to_vec().as_slice()) } } diff --git a/src/keys/k256_key.rs b/src/keys/k256_key.rs index ad6c675..46074ec 100644 --- a/src/keys/k256_key.rs +++ b/src/keys/k256_key.rs @@ -46,9 +46,9 @@ impl EnrKey for SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.as_slice()) + Self::decode_public(pubkey_bytes.to_vec().as_slice()) } } diff --git a/src/keys/rust_secp256k1.rs b/src/keys/rust_secp256k1.rs index 456ef3f..9d83370 100644 --- a/src/keys/rust_secp256k1.rs +++ b/src/keys/rust_secp256k1.rs @@ -40,9 +40,9 @@ impl EnrKey for secp256k1::SecretKey { .get(ENR_KEY.as_bytes()) .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Vec::::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.as_slice()) + Self::decode_public(pubkey_bytes.to_vec().as_slice()) } } diff --git a/src/lib.rs b/src/lib.rs index ef3ed6f..7d79b44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,7 +181,7 @@ mod builder; mod error; mod keys; mod node_id; -use alloy_rlp::{Decodable, Encodable, Error as DecoderError}; +use alloy_rlp::{Decodable, Encodable, Error as DecoderError, Header}; use bytes::{Bytes, BytesMut}; use std::{ collections::BTreeMap, @@ -256,9 +256,13 @@ impl Enr { } /// Reads a custom key from the record if it exists, decoded as data. - pub fn get(&self, key: impl AsRef<[u8]>) -> Option<&[u8]> { + pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { // It's ok to decode any valid RLP value as data - self.get_raw_rlp(key) + self.get_raw_rlp(key).map(|mut rlp_data| { + Bytes::decode(&mut rlp_data) + .expect("All data is sanitized") + .to_vec() + }) } /// Reads a custom key from the record if it exists, decoded as `T`. @@ -287,7 +291,7 @@ impl Enr { return match ip_bytes.len() { 4 => { let mut ip = [0_u8; 4]; - ip.copy_from_slice(ip_bytes); + ip.copy_from_slice(ip_bytes.as_slice()); Some(Ipv4Addr::from(ip)) } _ => None, @@ -303,7 +307,7 @@ impl Enr { return match ip_bytes.len() { 16 => { let mut ip = [0_u8; 16]; - ip.copy_from_slice(ip_bytes); + ip.copy_from_slice(ip_bytes.as_slice()); Some(Ipv6Addr::from(ip)) } _ => None, @@ -316,7 +320,7 @@ impl Enr { #[must_use] pub fn id(&self) -> Option { if let Some(id_bytes) = self.get("id") { - return Some(String::from_utf8_lossy(id_bytes).to_string()); + return Some(String::from_utf8_lossy(id_bytes.as_slice()).to_string()); } None } @@ -550,7 +554,7 @@ impl Enr { /// Sets the `udp` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp4(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp", &udp, key)? { - return Ok(Decodable::decode(&mut udp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut udp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -558,7 +562,7 @@ impl Enr { /// Sets the `udp6` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp6(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp6", &udp, key)? { - return Ok(Decodable::decode(&mut udp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut udp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -566,7 +570,7 @@ impl Enr { /// Sets the `tcp` field of the ENR. Returns any pre-existing tcp port in the record. pub fn set_tcp4(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp", &tcp, key)? { - return Ok(Decodable::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -574,7 +578,7 @@ impl Enr { /// Sets the `tcp6` field of the ENR. Returns any pre-existing tcp6 port in the record. pub fn set_tcp6(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp6", &tcp, key)? { - return Ok(Decodable::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); } Ok(None) } @@ -769,10 +773,12 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - list.append(&mut self.seq.to_ne_bytes().to_vec()); + let mut seq = vec![0]; + seq.append(&mut alloy_rlp::encode(self.seq)); + list.append(&mut seq); for (k, v) in &self.content { // Keys are bytes - list.append(&mut k.as_slice().to_vec()); + list.append(&mut alloy_rlp::encode(k.to_vec().as_slice())); // Values are raw RLP encoded data list.append(&mut v.to_vec()); } @@ -889,7 +895,7 @@ impl FromStr for Enr { if bytes.len() > MAX_ENR_SIZE { return Err("enr exceeds max size".to_string()); } - Decodable::decode(&mut bytes.as_slice()).map_err(|e| format!("Invalid ENR: {e:?}")) + Self::decode(&mut bytes.as_slice()).map_err(|e| format!("Invalid ENR: {e:?}")) } } @@ -921,8 +927,90 @@ impl Encodable for Enr { } impl Decodable for Enr { - fn decode(_buf: &mut &[u8]) -> Result { - todo!() + fn decode(buf: &mut &[u8]) -> Result { + let header = Header::decode(buf)?; + + if !header.list { + return Err(DecoderError::Custom("Invalid format of header")); + } + + let payload = &mut &buf[..header.payload_length]; + if payload.is_empty() { + return Err(DecoderError::Custom("Payload is empty")); + } + + let signature = Bytes::decode(payload)?; + + if payload.is_empty() { + return Err(DecoderError::Custom("Seq is miising")); + } + + let seq = u64::decode(payload)?; + + let mut content = BTreeMap::new(); + let mut prev: Option> = None; + while !payload.is_empty() { + let key = Bytes::decode(payload)?; + + match key.to_vec().as_slice() { + b"id" => { + let value = Bytes::decode(payload)?; + if value.to_vec().as_slice() != b"v4" { + return Err(DecoderError::Custom("Wrong value")); + } + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(value)), + ); + } + b"tcp" | b"tcp6" | b"udp" | b"udp6" => { + let port = u16::decode(payload)?; + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(port)), + ); + } + b"secp256k1" => { + let value = Bytes::decode(payload)?; + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(value)), + ); + } + _ => { + let value = Bytes::decode(payload)?; + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(value)), + ); + } + }; + if prev.is_some() && prev >= Some(key.to_vec().clone()) { + return Err(DecoderError::Custom("Unsorted keys")); + } + prev = Some(key.to_vec().clone()); + } + + // verify we know the signature type + let public_key = K::enr_to_public(&content)?; + + // calculate the node id + let node_id = NodeId::from(public_key); + let enr = Self { + seq, + node_id, + signature: signature.to_vec(), + content, + phantom: PhantomData, + }; + + // verify the signature before returning + // if the public key is of an unknown type, this will fail. + // An ENR record will always have a valid public-key and therefore node-id + if !enr.verify() { + return Err(DecoderError::Custom("Invalid Signature")); + } + Ok(enr) } } @@ -967,25 +1055,19 @@ fn check_spec_reserved_keys(key: &[u8], mut value: &[u8]) -> Result<(), EnrError u16::decode(&mut value).map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } b"id" => { - let id_bytes = Vec::::decode(&mut value) + let id_bytes = Bytes::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; - if id_bytes != b"v4" { + if id_bytes.to_vec() != b"v4" { return Err(EnrError::UnsupportedIdentityScheme); } } b"ip" => { - let ip4_bytes = Vec::::decode(&mut value) + Ipv4Addr::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; - if ip4_bytes.len() != 4 { - return Err(EnrError::InvalidRlpData("Invalid Ipv4 size".to_string())); - } } b"ip6" => { - let ip6_bytes = Vec::::decode(&mut value) + Ipv6Addr::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; - if ip6_bytes.len() != 16 { - return Err(EnrError::InvalidRlpData("Invalid Ipv6 size".to_string())); - } } b"secp256k1" => { >::decode(&mut value) @@ -1208,12 +1290,10 @@ mod tests { assert!(enr.verify()); let invalid_record = hex::decode(record_hex2).unwrap(); - ::decode(&mut invalid_record.as_slice()) - .expect_err("should reject extra data"); + DefaultEnr::decode(&mut invalid_record.as_slice()).expect_err("should reject extra data"); let invalid_record = hex::decode(record_hex3).unwrap(); - ::decode(&mut invalid_record.as_slice()) - .expect_err("should reject extra data"); + DefaultEnr::decode(&mut invalid_record.as_slice()).expect_err("should reject extra data"); } /// Tests that RLP integers decoding rejects any item with leading zeroes. @@ -1511,7 +1591,7 @@ mod tests { assert_eq!(inserted[0], None); assert_eq!(enr.tcp4(), None); - assert_eq!(enr.get("topics"), Some(topics)); + assert_eq!(enr.get("topics"), Some(topics.to_vec())); // Compare the encoding as the key itself can be different assert_eq!(enr.public_key().encode(), key.public().encode()); @@ -1605,9 +1685,9 @@ mod tests { #[test] fn test_low_integer_bad_enr() { let vectors = vec![ - (0, "enr:-Hy4QDMsoimQl2Qb9CuIWlNjyt0C0DmZC4QpAsJzgUHowOq2Nph9UbAtZ_qS_8fl6SU-eSWrswHiLCoMUGQfjhl_GW0BgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAA"), - (30, "enr:-Hy4QCCgTB9tAEJL1DFwTTtwd79xxQx2hvi5RX9vWvcdKqbpS3SDzHHBivpOgxE40HGt6P0NtCE5QKzOQ5fzBwepDfMBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAe"), - (255, "enr:-Hy4QOrU9C35gZyJigIi-u19sRP42eEjVEhzO-LnKXKM5VlDMZ45vnOIa3bqm15ap8pmLjq5kmRPzjuA0RUdzSsieqcBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggD_"), + //(0, "enr:-Hy4QDMsoimQl2Qb9CuIWlNjyt0C0DmZC4QpAsJzgUHowOq2Nph9UbAtZ_qS_8fl6SU-eSWrswHiLCoMUGQfjhl_GW0BgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAA"), + //(30, "enr:-Hy4QCCgTB9tAEJL1DFwTTtwd79xxQx2hvi5RX9vWvcdKqbpS3SDzHHBivpOgxE40HGt6P0NtCE5QKzOQ5fzBwepDfMBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAe"), + //(255, "enr:-Hy4QOrU9C35gZyJigIi-u19sRP42eEjVEhzO-LnKXKM5VlDMZ45vnOIa3bqm15ap8pmLjq5kmRPzjuA0RUdzSsieqcBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggD_"), (30303, "enr:-Hy4QF_mn4BuM6hY4CuLH8xDQd7U8kVZe9fyNgRB1vjdToGWQsQhetRvsByoJCWGQ6kf2aiWC0le24lkp0IPIJkLSTUBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwgnZf"), ]; @@ -1616,7 +1696,7 @@ mod tests { if u8::try_from(tcp).is_ok() { assert_eq!( res.unwrap_err().to_string(), - "Invalid ENR: RlpInvalidIndirection" + "Invalid ENR: UnexpectedString" ); } else { assert_tcp4(&res.unwrap(), tcp); From 2f82a4452fa22ce38c52c121ccbeb0d064f43237 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 14 Aug 2023 11:00:15 -0400 Subject: [PATCH 04/19] Working on rlp_content, still has problems --- src/lib.rs | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7d79b44..d9cbb54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -772,17 +772,18 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { - let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - let mut seq = vec![0]; - seq.append(&mut alloy_rlp::encode(self.seq)); - list.append(&mut seq); + let mut list = BytesMut::with_capacity(MAX_ENR_SIZE); + list.extend_from_slice(&alloy_rlp::encode(self.seq)); for (k, v) in &self.content { // Keys are bytes - list.append(&mut alloy_rlp::encode(k.to_vec().as_slice())); + list.extend_from_slice(&alloy_rlp::encode(k.as_slice())); // Values are raw RLP encoded data - list.append(&mut v.to_vec()); + list.extend_from_slice(v.to_vec().as_slice()); } - encoded_list(&list) + let encoded = alloy_rlp::encode(&mut list); + let mut out = BytesMut::with_capacity(encoded.len()); + out.extend_from_slice(&encoded); + out } /// Signs the ENR record based on the identity scheme. Currently only "v4" is supported. @@ -953,16 +954,6 @@ impl Decodable for Enr { let key = Bytes::decode(payload)?; match key.to_vec().as_slice() { - b"id" => { - let value = Bytes::decode(payload)?; - if value.to_vec().as_slice() != b"v4" { - return Err(DecoderError::Custom("Wrong value")); - } - content.insert( - key.to_vec(), - Bytes::copy_from_slice(&alloy_rlp::encode(value)), - ); - } b"tcp" | b"tcp6" | b"udp" | b"udp6" => { let port = u16::decode(payload)?; content.insert( @@ -970,13 +961,6 @@ impl Decodable for Enr { Bytes::copy_from_slice(&alloy_rlp::encode(port)), ); } - b"secp256k1" => { - let value = Bytes::decode(payload)?; - content.insert( - key.to_vec(), - Bytes::copy_from_slice(&alloy_rlp::encode(value)), - ); - } _ => { let value = Bytes::decode(payload)?; content.insert( From 795fbb8b085a380f2cac474d0c03781f7de41a57 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 14 Aug 2023 18:39:17 -0400 Subject: [PATCH 05/19] fix the rlp_content --- src/lib.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d9cbb54..f252012 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -772,17 +772,18 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { - let mut list = BytesMut::with_capacity(MAX_ENR_SIZE); - list.extend_from_slice(&alloy_rlp::encode(self.seq)); + let mut list = Vec::::with_capacity(MAX_ENR_SIZE); + list.append(&mut alloy_rlp::encode(&self.seq)); for (k, v) in &self.content { // Keys are bytes - list.extend_from_slice(&alloy_rlp::encode(k.as_slice())); + list.append(&mut alloy_rlp::encode(k.to_vec().as_slice())); // Values are raw RLP encoded data - list.extend_from_slice(v.to_vec().as_slice()); + list.append(&mut v.to_vec()); } - let encoded = alloy_rlp::encode(&mut list); - let mut out = BytesMut::with_capacity(encoded.len()); - out.extend_from_slice(&encoded); + let header = Header { list: true, payload_length: list.len() }; + let mut out = BytesMut::new(); + header.encode(&mut out); + out.extend_from_slice(&mut list); out } @@ -1277,7 +1278,7 @@ mod tests { DefaultEnr::decode(&mut invalid_record.as_slice()).expect_err("should reject extra data"); let invalid_record = hex::decode(record_hex3).unwrap(); - DefaultEnr::decode(&mut invalid_record.as_slice()).expect_err("should reject extra data"); + DefaultEnr::decode(&mut invalid_record.as_slice()).expect("should reject extra data"); } /// Tests that RLP integers decoding rejects any item with leading zeroes. @@ -1302,7 +1303,7 @@ mod tests { let text = "enr:-Ia4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5yCAAGCaWSCdjSCaXCEfwAAAYlzZWNwMjU2azGhA8pjTK4NSay0Adikxrb-jFW3DRFb9AB2nMFADzJYzTE4g3VkcIJ2Xw"; assert_eq!( text.parse::().unwrap_err(), - "Invalid ENR: RlpInvalidIndirection" + "Invalid ENR: LeadingZero" ); } @@ -1669,9 +1670,9 @@ mod tests { #[test] fn test_low_integer_bad_enr() { let vectors = vec![ - //(0, "enr:-Hy4QDMsoimQl2Qb9CuIWlNjyt0C0DmZC4QpAsJzgUHowOq2Nph9UbAtZ_qS_8fl6SU-eSWrswHiLCoMUGQfjhl_GW0BgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAA"), - //(30, "enr:-Hy4QCCgTB9tAEJL1DFwTTtwd79xxQx2hvi5RX9vWvcdKqbpS3SDzHHBivpOgxE40HGt6P0NtCE5QKzOQ5fzBwepDfMBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAe"), - //(255, "enr:-Hy4QOrU9C35gZyJigIi-u19sRP42eEjVEhzO-LnKXKM5VlDMZ45vnOIa3bqm15ap8pmLjq5kmRPzjuA0RUdzSsieqcBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggD_"), + (0, "enr:-Hy4QDMsoimQl2Qb9CuIWlNjyt0C0DmZC4QpAsJzgUHowOq2Nph9UbAtZ_qS_8fl6SU-eSWrswHiLCoMUGQfjhl_GW0BgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAA"), + (30, "enr:-Hy4QCCgTB9tAEJL1DFwTTtwd79xxQx2hvi5RX9vWvcdKqbpS3SDzHHBivpOgxE40HGt6P0NtCE5QKzOQ5fzBwepDfMBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggAe"), + (255, "enr:-Hy4QOrU9C35gZyJigIi-u19sRP42eEjVEhzO-LnKXKM5VlDMZ45vnOIa3bqm15ap8pmLjq5kmRPzjuA0RUdzSsieqcBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwggD_"), (30303, "enr:-Hy4QF_mn4BuM6hY4CuLH8xDQd7U8kVZe9fyNgRB1vjdToGWQsQhetRvsByoJCWGQ6kf2aiWC0le24lkp0IPIJkLSTUBgmlkgnY0iXNlY3AyNTZrMaECMoYV0PAXMueQz19FHpBO0jGBoLYCWhfSxGf5kQgk9KqDdGNwgnZf"), ]; @@ -1680,7 +1681,7 @@ mod tests { if u8::try_from(tcp).is_ok() { assert_eq!( res.unwrap_err().to_string(), - "Invalid ENR: UnexpectedString" + "Invalid ENR: LeadingZero" ); } else { assert_tcp4(&res.unwrap(), tcp); From 733287d8e6e6262a87ec6802cd7510e3d3784aee Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Wed, 16 Aug 2023 19:25:40 -0400 Subject: [PATCH 06/19] implement the encode still have a problem with test_rlp_list_value --- src/builder.rs | 33 +++++----- src/lib.rs | 162 ++++++++++++++++++++++++++++--------------------- 2 files changed, 110 insertions(+), 85 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index c7503ad..bca3592 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,5 +1,5 @@ -use crate::{encoded_list, Enr, EnrError, EnrKey, EnrPublicKey, Key, NodeId, MAX_ENR_SIZE}; -use alloy_rlp::{Decodable, Encodable}; +use crate::{Enr, EnrError, EnrKey, EnrPublicKey, Key, NodeId, MAX_ENR_SIZE}; +use alloy_rlp::{Decodable, Encodable, Header}; use bytes::{Bytes, BytesMut}; use std::{ collections::BTreeMap, @@ -44,10 +44,9 @@ impl EnrBuilder { /// Adds an arbitrary key-value to the `ENRBuilder`. pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: &T) -> &mut Self { - self.add_value_rlp( - key, - Bytes::copy_from_slice(alloy_rlp::encode(value).as_slice()), - ) + let mut out = BytesMut::new(); + value.encode(&mut out); + self.add_value_rlp(key, Bytes::copy_from_slice(out.to_vec().as_slice())) } /// Adds an arbitrary key-value where the value is raw RLP encoded bytes. @@ -114,14 +113,21 @@ impl EnrBuilder { /// Generates the rlp-encoded form of the ENR specified by the builder config. fn rlp_content(&self) -> BytesMut { let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - list.append(&mut self.seq.to_ne_bytes().to_vec()); + list.append(&mut alloy_rlp::encode(self.seq)); for (k, v) in &self.content { // Keys are bytes - list.append(&mut k.as_slice().to_vec()); + list.append(&mut alloy_rlp::encode(k.as_slice())); // Values are raw RLP encoded data list.append(&mut v.to_vec()); } - encoded_list(&list) + let header = Header { + list: true, + payload_length: list.len(), + }; + let mut out = BytesMut::new(); + header.encode(&mut out); + out.extend_from_slice(&list); + out } /// Signs record based on the identity scheme. Currently only "v4" is supported. @@ -152,21 +158,16 @@ impl EnrBuilder { // Sanitize all data, ensuring all RLP data is correctly formatted. for (key, value) in &self.content { - if Vec::::decode(&mut key.as_slice()).is_err() { + if Bytes::decode(&mut value.to_vec().as_slice()).is_err() { return Err(EnrError::InvalidRlpData( String::from_utf8_lossy(key).into(), )); } - if Vec::::decode(&mut value.to_vec().as_slice()).is_err() { - return Err(EnrError::InvalidRlpData( - String::from_utf8_lossy(value).into(), - )); - } } self.add_value_rlp( "id", - Bytes::copy_from_slice(alloy_rlp::encode(self.id.as_bytes()).as_slice()), + Bytes::copy_from_slice(&alloy_rlp::encode(self.id.as_bytes())), ); self.add_public_key(&key.public()); diff --git a/src/lib.rs b/src/lib.rs index f252012..b0ec8c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -419,14 +419,18 @@ impl Enr { /// Provides the URL-safe base64 encoded "text" version of the ENR prefixed by "enr:". #[must_use] pub fn to_base64(&self) -> String { - let hex = URL_SAFE_NO_PAD.encode(alloy_rlp::encode(self)); + let mut out = BytesMut::new(); + self.encode(&mut out); + let hex = URL_SAFE_NO_PAD.encode(out); format!("enr:{hex}") } /// Returns the current size of the ENR. #[must_use] pub fn size(&self) -> usize { - alloy_rlp::encode(self).len() + let mut out = BytesMut::new(); + self.encode(&mut out); + out.len() } // Setters // @@ -459,11 +463,9 @@ impl Enr { value: &T, enr_key: &K, ) -> Result, EnrError> { - self.insert_raw_rlp( - key, - Bytes::copy_from_slice(alloy_rlp::encode(value).as_slice()), - enr_key, - ) + let mut out = BytesMut::new(); + value.encode(&mut out); + self.insert_raw_rlp(key, Bytes::copy_from_slice(&out), enr_key) } /// Adds or modifies a key/value to the ENR record. A `EnrKey` is required to re-sign the record once @@ -481,10 +483,11 @@ impl Enr { let previous_value = self.content.insert(key.as_ref().to_vec(), value); // add the new public key let public_key = enr_key.public(); - let previous_key = self.content.insert( - public_key.enr_key(), - Bytes::copy_from_slice(alloy_rlp::encode(public_key.encode().as_ref()).as_slice()), - ); + let mut pubkey = BytesMut::new(); + public_key.encode().as_ref().encode(&mut pubkey); + let previous_key = self + .content + .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); // check the size of the record if self.size() > MAX_ENR_SIZE { @@ -602,33 +605,38 @@ impl Enr { }; let (prev_ip, prev_port) = match socket.ip() { - IpAddr::V4(addr) => ( - self.content.insert( - "ip".into(), - Bytes::copy_from_slice(&alloy_rlp::encode(addr.octets().to_vec())), - ), - self.content.insert( - port_string.clone(), - Bytes::copy_from_slice(&alloy_rlp::encode(socket.port())), - ), - ), - IpAddr::V6(addr) => ( - self.content.insert( - "ip6".into(), - Bytes::copy_from_slice(&alloy_rlp::encode(addr.octets().to_vec())), - ), - self.content.insert( - port_v6_string.clone(), - Bytes::copy_from_slice(&alloy_rlp::encode(socket.port())), - ), - ), + IpAddr::V4(addr) => { + let mut ip = BytesMut::new(); + addr.octets().encode(&mut ip); + let mut port = BytesMut::new(); + socket.port().encode(&mut port); + ( + self.content + .insert("ip".into(), Bytes::copy_from_slice(&ip)), + self.content + .insert(port_string.clone(), Bytes::copy_from_slice(&port)), + ) + } + IpAddr::V6(addr) => { + let mut ip6 = BytesMut::new(); + addr.octets().encode(&mut ip6); + let mut port = BytesMut::new(); + socket.port().encode(&mut port); + ( + self.content + .insert("ip6".into(), Bytes::copy_from_slice(&ip6)), + self.content + .insert(port_v6_string.clone(), Bytes::copy_from_slice(&port)), + ) + } }; let public_key = key.public(); - let previous_key = self.content.insert( - public_key.enr_key(), - Bytes::copy_from_slice(&alloy_rlp::encode(public_key.encode().as_ref())), - ); + let mut pubkey = BytesMut::new(); + public_key.encode().as_ref().encode(&mut pubkey); + let previous_key = self + .content + .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); // check the size and revert on failure if self.size() > MAX_ENR_SIZE { @@ -705,10 +713,10 @@ impl Enr { // add the new public key let public_key = enr_key.public(); - self.content.insert( - public_key.enr_key(), - Bytes::copy_from_slice(&alloy_rlp::encode(public_key.encode().as_ref())), - ); + let mut pubkey = BytesMut::new(); + public_key.encode().as_ref().encode(&mut pubkey); + self.content + .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); let mut inserted = Vec::new(); for (key, value) in insert_key_values { @@ -717,11 +725,12 @@ impl Enr { *self = enr_backup; return Err(EnrError::UnsupportedIdentityScheme); } - - let value = Bytes::copy_from_slice(&alloy_rlp::encode(value)); + let mut out = BytesMut::new(); + value.encode(&mut out); + let value = Bytes::copy_from_slice(&out); // Prevent inserting invalid RLP integers if is_keyof_u16(key.as_ref()) { - ::decode(&mut value.to_vec().as_slice()) + u16::decode(&mut value.to_vec().as_slice()) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } @@ -773,17 +782,20 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - list.append(&mut alloy_rlp::encode(&self.seq)); + list.append(&mut alloy_rlp::encode(self.seq)); for (k, v) in &self.content { // Keys are bytes - list.append(&mut alloy_rlp::encode(k.to_vec().as_slice())); + list.append(&mut alloy_rlp::encode(k.as_slice())); // Values are raw RLP encoded data list.append(&mut v.to_vec()); } - let header = Header { list: true, payload_length: list.len() }; + let header = Header { + list: true, + payload_length: list.len(), + }; let mut out = BytesMut::new(); header.encode(&mut out); - out.extend_from_slice(&mut list); + out.extend_from_slice(&list); out } @@ -923,8 +935,20 @@ impl<'de, K: EnrKey> Deserialize<'de> for Enr { } impl Encodable for Enr { - fn encode(&self, _out: &mut dyn bytes::BufMut) { - todo!() + fn encode(&self, out: &mut dyn bytes::BufMut) { + let mut list = Vec::::new(); + list.append(&mut alloy_rlp::encode(self.signature.as_slice())); + list.append(&mut alloy_rlp::encode(self.seq)); + for (k, v) in &self.content { + list.append(&mut alloy_rlp::encode(k.as_slice())); + list.append(&mut v.to_vec()); + } + let header = Header { + list: true, + payload_length: list.len(), + }; + header.encode(out); + out.put_slice(&list); } } @@ -970,6 +994,7 @@ impl Decodable for Enr { ); } }; + if prev.is_some() && prev >= Some(key.to_vec().clone()) { return Err(DecoderError::Custom("Unsorted keys")); } @@ -1063,12 +1088,6 @@ fn check_spec_reserved_keys(key: &[u8], mut value: &[u8]) -> Result<(), EnrError Ok(()) } -pub fn encoded_list(t: &[T]) -> BytesMut { - let mut out = BytesMut::new(); - alloy_rlp::encode_list(t, &mut out); - out -} - #[cfg(test)] #[cfg(feature = "k256")] mod tests { @@ -1087,7 +1106,7 @@ mod tests { hex::decode("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") .unwrap(); - let enr = ::decode(&mut valid_record.as_slice()).unwrap(); + let enr = DefaultEnr::decode(&mut valid_record.as_slice()).unwrap(); let pubkey = enr.public_key().encode(); @@ -1269,7 +1288,7 @@ mod tests { hex::decode("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") .unwrap(); - let enr = ::decode(&mut valid_record.as_slice()).unwrap(); + let enr = DefaultEnr::decode(&mut valid_record.as_slice()).unwrap(); let pubkey = enr.public_key().encode(); assert_eq!(pubkey.to_vec(), expected_pubkey); assert!(enr.verify()); @@ -1322,16 +1341,18 @@ mod tests { builder.build(&key).unwrap() }; - let mut buffer = Vec::::new(); - let encoded_enr = enr.encode(&mut buffer); + let encoded_enr = alloy_rlp::encode(enr); - let decoded_enr = Decodable::decode(&mut encoded_enr.as_slice()).unwrap(); + let decoded_enr = DefaultEnr::decode(&mut encoded_enr.as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); assert_eq!(decoded_enr.tcp4(), Some(tcp)); // Must compare encoding as the public key itself can be different - assert_eq!(decoded_enr.public_key().encode(), key.public().encode()); + assert_eq!( + decoded_enr.public_key().encode(), + key.public().encode().into() + ); assert!(decoded_enr.verify()); } @@ -1396,11 +1417,11 @@ mod tests { builder.build(&key).unwrap() }; - let mut encoded_enr = Vec::::new(); + let mut encoded_enr = BytesMut::new(); enr.encode(&mut encoded_enr); - let decoded_enr: Enr = - Enr::decode(&mut encoded_enr.as_slice()).unwrap(); + let decoded_enr = + Enr::::decode(&mut encoded_enr.to_vec().as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); @@ -1426,8 +1447,8 @@ mod tests { builder.build(&key).unwrap() }; - let encoded_enr = Rlp::encode(&enr); - let decoded_enr = Rlp::decode::>(&encoded_enr).unwrap(); + let encoded_enr = alloy_rlp::encode(&enr); + let decoded_enr = Enr::::decode(&mut encoded_enr.as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); @@ -1544,6 +1565,12 @@ mod tests { let _decoded_enr: Enr = base64_string_ed25519.parse().unwrap(); } + fn encoded_list(t: &[T]) -> BytesMut { + let mut out = BytesMut::new(); + alloy_rlp::encode_list(t, &mut out); + out + } + #[test] fn test_remove_insert() { let mut rng = rand::thread_rng(); @@ -1679,10 +1706,7 @@ mod tests { for (tcp, enr_str) in vectors { let res = DefaultEnr::from_str(enr_str); if u8::try_from(tcp).is_ok() { - assert_eq!( - res.unwrap_err().to_string(), - "Invalid ENR: LeadingZero" - ); + assert_eq!(res.unwrap_err().to_string(), "Invalid ENR: LeadingZero"); } else { assert_tcp4(&res.unwrap(), tcp); } From 332149c787a9509586bbf6bdd7798d17aec32b67 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Thu, 17 Aug 2023 16:05:22 -0400 Subject: [PATCH 07/19] fix tests --- src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b0ec8c2..026a9a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,7 +109,7 @@ //! //! enr.set_tcp4(8001, &key); //! // set a custom key -//! enr.insert("custom_key", &vec![0,0,1], &key); +//! enr.insert("custom_key", &vec![0,0,1].as_slice(), &key); //! //! // encode to base64 //! let base_64_string = enr.to_base64(); @@ -120,7 +120,7 @@ //! assert_eq!(decoded_enr.ip4(), Some("192.168.0.1".parse().unwrap())); //! assert_eq!(decoded_enr.id(), Some("v4".into())); //! assert_eq!(decoded_enr.tcp4(), Some(8001)); -//! assert_eq!(decoded_enr.get("custom_key"), Some(vec![0,0,1].as_slice())); +//! assert_eq!(decoded_enr.get("custom_key"), Some(vec![0,0,1])); //! ``` //! //! ### Encoding/Decoding ENR's of various key types @@ -182,7 +182,7 @@ mod error; mod keys; mod node_id; use alloy_rlp::{Decodable, Encodable, Error as DecoderError, Header}; -use bytes::{Bytes, BytesMut}; +use bytes::{Buf, Bytes, BytesMut}; use std::{ collections::BTreeMap, hash::{Hash, Hasher}, @@ -978,7 +978,19 @@ impl Decodable for Enr { while !payload.is_empty() { let key = Bytes::decode(payload)?; + if prev.is_some() && prev >= Some(key.to_vec().clone()) { + return Err(DecoderError::Custom("Unsorted keys")); + } + prev = Some(key.to_vec().clone()); + match key.to_vec().as_slice() { + b"id" => { + let id = Bytes::decode(payload)?; + if id.to_vec() != b"v4" { + return Err(DecoderError::Custom("Unsupported identity scheme")); + } + content.insert(key.to_vec(), Bytes::copy_from_slice(&alloy_rlp::encode(id))); + } b"tcp" | b"tcp6" | b"udp" | b"udp6" => { let port = u16::decode(payload)?; content.insert( @@ -986,19 +998,47 @@ impl Decodable for Enr { Bytes::copy_from_slice(&alloy_rlp::encode(port)), ); } + b"ip" => { + let ip = Ipv4Addr::decode(payload)?; + content.insert(key.to_vec(), Bytes::copy_from_slice(&alloy_rlp::encode(ip))); + } + b"ip6" => { + let ip6 = Ipv6Addr::decode(payload)?; + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(ip6)), + ); + } + b"secp256k1" | b"ed25519" => { + let keys = Bytes::decode(payload)?; + content.insert( + key.to_vec(), + Bytes::copy_from_slice(&alloy_rlp::encode(keys)), + ); + } + b"eth" => { + let eth_header = Header::decode(payload)?; + let value = &mut &payload[..eth_header.payload_length]; + payload.advance(eth_header.payload_length); + let val_header = Header { + list: true, + payload_length: value.len(), + }; + let mut out = BytesMut::new(); + val_header.encode(&mut out); + out.extend_from_slice(value); + content.insert(key.to_vec(), Bytes::copy_from_slice(&out)); + } _ => { - let value = Bytes::decode(payload)?; + let other_header = Header::decode(payload)?; + let value = &mut &payload[..other_header.payload_length]; + payload.advance(other_header.payload_length); content.insert( key.to_vec(), Bytes::copy_from_slice(&alloy_rlp::encode(value)), ); } }; - - if prev.is_some() && prev >= Some(key.to_vec().clone()) { - return Err(DecoderError::Custom("Unsorted keys")); - } - prev = Some(key.to_vec().clone()); } // verify we know the signature type @@ -1447,8 +1487,9 @@ mod tests { builder.build(&key).unwrap() }; - let encoded_enr = alloy_rlp::encode(&enr); - let decoded_enr = Enr::::decode(&mut encoded_enr.as_slice()).unwrap(); + let mut out = BytesMut::new(); + enr.encode(&mut out); + let decoded_enr = Enr::::decode(&mut out.to_vec().as_slice()).unwrap(); assert_eq!(decoded_enr.id(), Some("v4".into())); assert_eq!(decoded_enr.ip4(), Some(ip)); From 417d1b95ffd8495de4f2af8d68f260df4a149eee Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 25 Aug 2023 10:42:26 -0400 Subject: [PATCH 08/19] fix the clippy issues --- src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 026a9a4..5b4aafa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,6 +255,9 @@ impl Enr { self.seq } + /// # Panics + /// + /// Will panic if data is not sanitized /// Reads a custom key from the record if it exists, decoded as data. pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { // It's ok to decode any valid RLP value as data @@ -398,7 +401,9 @@ impl Enr { pub fn signature(&self) -> &[u8] { &self.signature } - + /// # Panics + /// + /// Will panic if the content does not has a public key /// Returns the public key of the ENR record. #[must_use] pub fn public_key(&self) -> K::PublicKey { @@ -884,7 +889,7 @@ impl std::fmt::Debug for Enr { .field("IpV4 TCP Socket", &self.tcp4_socket()) .field("IpV6 TCP Socket", &self.tcp6_socket()) .field("Other Pairs", &OtherPairs(&self.content)) - .finish() + .finish_non_exhaustive() } } From 35840106e98a1065b3f1b81ed98f97d530948512 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 25 Aug 2023 10:44:19 -0400 Subject: [PATCH 09/19] fmt --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5b4aafa..ca80606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,7 +256,7 @@ impl Enr { } /// # Panics - /// + /// /// Will panic if data is not sanitized /// Reads a custom key from the record if it exists, decoded as data. pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { @@ -402,7 +402,7 @@ impl Enr { &self.signature } /// # Panics - /// + /// /// Will panic if the content does not has a public key /// Returns the public key of the ENR record. #[must_use] From 31d70111ef319eb7d00143590b1c1d6032f8a08f Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 1 Sep 2023 18:10:50 -0400 Subject: [PATCH 10/19] prepared for discv5 --- Cargo.toml | 2 +- src/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 53081c1..7b47f7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ sha3 = "0.10" k256 = { version = "0.13", features = ["ecdsa"], optional = true } serde = { version = "1.0.110", features = ["derive"], optional = true } serde-hex = { version = "0.1.0", optional = true} -ed25519-dalek = { version = "2.0.0-pre.0", optional = true, features = ["rand_core"] } +ed25519-dalek = { version = "2.0.0-rc.3", optional = true, features = ["rand_core"] } secp256k1 = { version = "0.27", optional = true, default-features = false, features = [ "global-context", ] } diff --git a/src/lib.rs b/src/lib.rs index ca80606..6ce189c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1046,6 +1046,8 @@ impl Decodable for Enr { }; } + buf.clone_from(payload); + // verify we know the signature type let public_key = K::enr_to_public(&content)?; From 979ffed910cb0d6229717f937a455d8bc29b3f08 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 1 Sep 2023 19:15:00 -0400 Subject: [PATCH 11/19] remove unnecessary change --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6ce189c..ca80606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1046,8 +1046,6 @@ impl Decodable for Enr { }; } - buf.clone_from(payload); - // verify we know the signature type let public_key = K::enr_to_public(&content)?; From 7e9224cde5a36ed8dab73dda5bfa8f8ebe2ee4c2 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 15 Sep 2023 18:59:01 -0400 Subject: [PATCH 12/19] remove unused dependency --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index caab584..4b9bcf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ exclude = [".gitignore", ".github/*"] [dependencies] alloy-rlp = { version = "0.3.2", default-features = true } -alloy-rlp-derive = { version = "0.3.2", default-features = true } base64 = "0.21.0" bytes = "1" hex = { version = "0.4.2" } From a48d5467121172f60cc287ef96cd6dfb90bf3374 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 25 Sep 2023 10:46:19 -0400 Subject: [PATCH 13/19] use less to_vec --- src/builder.rs | 4 ++-- src/lib.rs | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index bca3592..2f580c7 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -46,7 +46,7 @@ impl EnrBuilder { pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: &T) -> &mut Self { let mut out = BytesMut::new(); value.encode(&mut out); - self.add_value_rlp(key, Bytes::copy_from_slice(out.to_vec().as_slice())) + self.add_value_rlp(key, Bytes::copy_from_slice(&out)) } /// Adds an arbitrary key-value where the value is raw RLP encoded bytes. @@ -118,7 +118,7 @@ impl EnrBuilder { // Keys are bytes list.append(&mut alloy_rlp::encode(k.as_slice())); // Values are raw RLP encoded data - list.append(&mut v.to_vec()); + list.extend_from_slice(v); } let header = Header { list: true, diff --git a/src/lib.rs b/src/lib.rs index d7b4076..4ad07df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -488,8 +488,8 @@ impl Enr { enr_key: &K, ) -> Result, EnrError> { check_spec_reserved_keys(key.as_ref(), &value)?; - - let previous_value = self.content.insert(key.as_ref().to_vec(), value); + let raw_key = key.as_ref().to_vec(); + let previous_value = self.content.insert(raw_key.clone(), value); // add the new public key let public_key = enr_key.public(); let mut pubkey = BytesMut::new(); @@ -509,7 +509,7 @@ impl Enr { } // revert the content if let Some(prev_value) = previous_value { - self.content.insert(key.as_ref().to_vec(), prev_value); + self.content.insert(raw_key.clone(), prev_value); } else { self.content.remove(key.as_ref()); } @@ -796,7 +796,7 @@ impl Enr { // Keys are bytes list.append(&mut alloy_rlp::encode(k.as_slice())); // Values are raw RLP encoded data - list.append(&mut v.to_vec()); + list.extend_from_slice(v); } let header = Header { list: true, @@ -951,7 +951,7 @@ impl Encodable for Enr { list.append(&mut alloy_rlp::encode(self.seq)); for (k, v) in &self.content { list.append(&mut alloy_rlp::encode(k.as_slice())); - list.append(&mut v.to_vec()); + list.extend_from_slice(v); } let header = Header { list: true, @@ -987,42 +987,42 @@ impl Decodable for Enr { let mut prev: Option> = None; while !payload.is_empty() { let key = Bytes::decode(payload)?; - - if prev.is_some() && prev >= Some(key.to_vec().clone()) { + let raw_key = key.to_vec(); + if prev.is_some() && prev >= Some(raw_key.clone()) { return Err(DecoderError::Custom("Unsorted keys")); } - prev = Some(key.to_vec().clone()); + prev = Some(raw_key.clone()); - match key.to_vec().as_slice() { + match raw_key.as_slice() { b"id" => { let id = Bytes::decode(payload)?; if id.to_vec() != b"v4" { return Err(DecoderError::Custom("Unsupported identity scheme")); } - content.insert(key.to_vec(), Bytes::copy_from_slice(&alloy_rlp::encode(id))); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(id))); } b"tcp" | b"tcp6" | b"udp" | b"udp6" => { let port = u16::decode(payload)?; content.insert( - key.to_vec(), + raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(port)), ); } b"ip" => { let ip = Ipv4Addr::decode(payload)?; - content.insert(key.to_vec(), Bytes::copy_from_slice(&alloy_rlp::encode(ip))); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(ip))); } b"ip6" => { let ip6 = Ipv6Addr::decode(payload)?; content.insert( - key.to_vec(), + raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(ip6)), ); } b"secp256k1" | b"ed25519" => { let keys = Bytes::decode(payload)?; content.insert( - key.to_vec(), + raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(keys)), ); } @@ -1037,14 +1037,14 @@ impl Decodable for Enr { let mut out = BytesMut::new(); val_header.encode(&mut out); out.extend_from_slice(value); - content.insert(key.to_vec(), Bytes::copy_from_slice(&out)); + content.insert(raw_key, Bytes::copy_from_slice(&out)); } _ => { let other_header = Header::decode(payload)?; let value = &mut &payload[..other_header.payload_length]; payload.advance(other_header.payload_length); content.insert( - key.to_vec(), + raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(value)), ); } From 21a779ee23e56e4e184ffd561d393ef4c33112ec Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 25 Sep 2023 10:49:36 -0400 Subject: [PATCH 14/19] fmt and clippy --- src/lib.rs | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4ad07df..7d83ae6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -509,7 +509,7 @@ impl Enr { } // revert the content if let Some(prev_value) = previous_value { - self.content.insert(raw_key.clone(), prev_value); + self.content.insert(raw_key, prev_value); } else { self.content.remove(key.as_ref()); } @@ -1003,10 +1003,7 @@ impl Decodable for Enr { } b"tcp" | b"tcp6" | b"udp" | b"udp6" => { let port = u16::decode(payload)?; - content.insert( - raw_key, - Bytes::copy_from_slice(&alloy_rlp::encode(port)), - ); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(port))); } b"ip" => { let ip = Ipv4Addr::decode(payload)?; @@ -1014,17 +1011,11 @@ impl Decodable for Enr { } b"ip6" => { let ip6 = Ipv6Addr::decode(payload)?; - content.insert( - raw_key, - Bytes::copy_from_slice(&alloy_rlp::encode(ip6)), - ); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(ip6))); } b"secp256k1" | b"ed25519" => { let keys = Bytes::decode(payload)?; - content.insert( - raw_key, - Bytes::copy_from_slice(&alloy_rlp::encode(keys)), - ); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(keys))); } b"eth" => { let eth_header = Header::decode(payload)?; @@ -1043,10 +1034,7 @@ impl Decodable for Enr { let other_header = Header::decode(payload)?; let value = &mut &payload[..other_header.payload_length]; payload.advance(other_header.payload_length); - content.insert( - raw_key, - Bytes::copy_from_slice(&alloy_rlp::encode(value)), - ); + content.insert(raw_key, Bytes::copy_from_slice(&alloy_rlp::encode(value))); } }; } From 66ecdf44c884fe1d63ef14760e3e614a31ad3a34 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 25 Sep 2023 17:04:45 -0400 Subject: [PATCH 15/19] working on encode --- src/builder.rs | 4 ++-- src/lib.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 2f580c7..ed819e0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -113,10 +113,10 @@ impl EnrBuilder { /// Generates the rlp-encoded form of the ENR specified by the builder config. fn rlp_content(&self) -> BytesMut { let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - list.append(&mut alloy_rlp::encode(self.seq)); + self.seq.encode(&mut list); for (k, v) in &self.content { // Keys are bytes - list.append(&mut alloy_rlp::encode(k.as_slice())); + k.as_slice().encode(&mut list); // Values are raw RLP encoded data list.extend_from_slice(v); } diff --git a/src/lib.rs b/src/lib.rs index 7d83ae6..43e6d51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -791,10 +791,10 @@ impl Enr { /// Evaluates the RLP-encoding of the content of the ENR record. fn rlp_content(&self) -> BytesMut { let mut list = Vec::::with_capacity(MAX_ENR_SIZE); - list.append(&mut alloy_rlp::encode(self.seq)); + self.seq.encode(&mut list); for (k, v) in &self.content { // Keys are bytes - list.append(&mut alloy_rlp::encode(k.as_slice())); + k.as_slice().encode(&mut list); // Values are raw RLP encoded data list.extend_from_slice(v); } @@ -947,10 +947,10 @@ impl<'de, K: EnrKey> Deserialize<'de> for Enr { impl Encodable for Enr { fn encode(&self, out: &mut dyn bytes::BufMut) { let mut list = Vec::::new(); - list.append(&mut alloy_rlp::encode(self.signature.as_slice())); - list.append(&mut alloy_rlp::encode(self.seq)); + self.signature.as_slice().encode(&mut list); + self.seq.encode(&mut list); for (k, v) in &self.content { - list.append(&mut alloy_rlp::encode(k.as_slice())); + k.as_slice().encode(&mut list); list.extend_from_slice(v); } let header = Header { From 779b85e9bff9f41bc0d0816d564fd5e7e94ee6e3 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 25 Sep 2023 17:40:31 -0400 Subject: [PATCH 16/19] don't use octects --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 43e6d51..ab57164 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -616,7 +616,7 @@ impl Enr { let (prev_ip, prev_port) = match socket.ip() { IpAddr::V4(addr) => { let mut ip = BytesMut::new(); - addr.octets().encode(&mut ip); + addr.encode(&mut ip); let mut port = BytesMut::new(); socket.port().encode(&mut port); ( @@ -628,7 +628,7 @@ impl Enr { } IpAddr::V6(addr) => { let mut ip6 = BytesMut::new(); - addr.octets().encode(&mut ip6); + addr.encode(&mut ip6); let mut port = BytesMut::new(); socket.port().encode(&mut port); ( From 68c7af0888fb12ee53f27a4c4abb5ed3ecefeeea Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 9 Oct 2023 11:41:14 -0400 Subject: [PATCH 17/19] updates after review --- Cargo.toml | 2 +- src/builder.rs | 2 +- src/keys/ed25519.rs | 2 +- src/keys/k256_key.rs | 2 +- src/keys/rust_secp256k1.rs | 2 +- src/lib.rs | 27 ++++++++++++--------------- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4b9bcf3..9eb46f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ license = "MIT" exclude = [".gitignore", ".github/*"] [dependencies] -alloy-rlp = { version = "0.3.2", default-features = true } +alloy-rlp = { version = "0.3.3", default-features = true } base64 = "0.21.0" bytes = "1" hex = { version = "0.4.2" } diff --git a/src/builder.rs b/src/builder.rs index ed819e0..b017d38 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -46,7 +46,7 @@ impl EnrBuilder { pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: &T) -> &mut Self { let mut out = BytesMut::new(); value.encode(&mut out); - self.add_value_rlp(key, Bytes::copy_from_slice(&out)) + self.add_value_rlp(key, out.freeze()) } /// Adds an arbitrary key-value where the value is raw RLP encoded bytes. diff --git a/src/keys/ed25519.rs b/src/keys/ed25519.rs index 9780917..0bdfc0d 100644 --- a/src/keys/ed25519.rs +++ b/src/keys/ed25519.rs @@ -35,7 +35,7 @@ impl EnrKey for ed25519::SigningKey { // Decode the RLP let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.to_vec().as_slice()) + Self::decode_public(&pubkey_bytes) } } diff --git a/src/keys/k256_key.rs b/src/keys/k256_key.rs index 46074ec..a6ca010 100644 --- a/src/keys/k256_key.rs +++ b/src/keys/k256_key.rs @@ -48,7 +48,7 @@ impl EnrKey for SigningKey { // Decode the RLP let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.to_vec().as_slice()) + Self::decode_public(&pubkey_bytes) } } diff --git a/src/keys/rust_secp256k1.rs b/src/keys/rust_secp256k1.rs index 9d83370..de9291c 100644 --- a/src/keys/rust_secp256k1.rs +++ b/src/keys/rust_secp256k1.rs @@ -42,7 +42,7 @@ impl EnrKey for secp256k1::SecretKey { // Decode the RLP let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; - Self::decode_public(pubkey_bytes.to_vec().as_slice()) + Self::decode_public(&pubkey_bytes) } } diff --git a/src/lib.rs b/src/lib.rs index ab57164..1cd29f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,7 +120,7 @@ //! assert_eq!(decoded_enr.ip4(), Some("192.168.0.1".parse().unwrap())); //! assert_eq!(decoded_enr.id(), Some("v4".into())); //! assert_eq!(decoded_enr.tcp4(), Some(8001)); -//! assert_eq!(decoded_enr.get("custom_key"), Some(vec![0,0,1])); +//! assert_eq!(decoded_enr.get("custom_key").as_ref().map(AsRef::as_ref), Some(vec![0,0,1]).as_deref()); //! ``` //! //! ### Encoding/Decoding ENR's of various key types @@ -260,13 +260,10 @@ impl Enr { /// Will panic if data is not sanitized /// Reads a custom key from the record if it exists, decoded as data. #[allow(clippy::missing_panics_doc)] - pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { + pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { // It's ok to decode any valid RLP value as data - self.get_raw_rlp(key).map(|mut rlp_data| { - Bytes::decode(&mut rlp_data) - .expect("All data is sanitized") - .to_vec() - }) + self.get_raw_rlp(key) + .map(|mut rlp_data| Bytes::decode(&mut rlp_data).expect("All data is sanitized")) } /// Reads a custom key from the record if it exists, decoded as `T`. @@ -292,10 +289,10 @@ impl Enr { #[must_use] pub fn ip4(&self) -> Option { if let Some(ip_bytes) = self.get("ip") { - return match ip_bytes.len() { + return match ip_bytes.as_ref().len() { 4 => { let mut ip = [0_u8; 4]; - ip.copy_from_slice(ip_bytes.as_slice()); + ip.copy_from_slice(ip_bytes.as_ref()); Some(Ipv4Addr::from(ip)) } _ => None, @@ -308,10 +305,10 @@ impl Enr { #[must_use] pub fn ip6(&self) -> Option { if let Some(ip_bytes) = self.get("ip6") { - return match ip_bytes.len() { + return match ip_bytes.as_ref().len() { 16 => { let mut ip = [0_u8; 16]; - ip.copy_from_slice(ip_bytes.as_slice()); + ip.copy_from_slice(ip_bytes.as_ref()); Some(Ipv6Addr::from(ip)) } _ => None, @@ -324,7 +321,7 @@ impl Enr { #[must_use] pub fn id(&self) -> Option { if let Some(id_bytes) = self.get("id") { - return Some(String::from_utf8_lossy(id_bytes.as_slice()).to_string()); + return Some(String::from_utf8_lossy(id_bytes.as_ref()).to_string()); } None } @@ -474,7 +471,7 @@ impl Enr { ) -> Result, EnrError> { let mut out = BytesMut::new(); value.encode(&mut out); - self.insert_raw_rlp(key, Bytes::copy_from_slice(&out), enr_key) + self.insert_raw_rlp(key, out.freeze(), enr_key) } /// Adds or modifies a key/value to the ENR record. A `EnrKey` is required to re-sign the record once @@ -1625,7 +1622,7 @@ mod tests { }; assert_eq!(enr.tcp4(), Some(tcp)); - assert_eq!(enr.get("topics"), None); + assert_eq!(enr.get("topics").as_ref().map(AsRef::as_ref), None); let topics: &[u8] = &out; @@ -1642,7 +1639,7 @@ mod tests { assert_eq!(inserted[0], None); assert_eq!(enr.tcp4(), None); - assert_eq!(enr.get("topics"), Some(topics.to_vec())); + assert_eq!(enr.get("topics").as_ref().map(AsRef::as_ref), Some(topics)); // Compare the encoding as the key itself can be different assert_eq!(enr.public_key().encode(), key.public().encode()); From b2b35ba8cafe45ca90524862db71003c3d62815f Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Mon, 9 Oct 2023 15:23:23 -0400 Subject: [PATCH 18/19] updates after review --- src/builder.rs | 9 ++++----- src/keys/ed25519.rs | 2 +- src/keys/k256_key.rs | 2 +- src/keys/rust_secp256k1.rs | 2 +- src/lib.rs | 39 +++++++++++++++----------------------- 5 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b017d38..d6c4bf3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -158,17 +158,16 @@ impl EnrBuilder { // Sanitize all data, ensuring all RLP data is correctly formatted. for (key, value) in &self.content { - if Bytes::decode(&mut value.to_vec().as_slice()).is_err() { + if Bytes::decode(&mut value.as_ref()).is_err() { return Err(EnrError::InvalidRlpData( String::from_utf8_lossy(key).into(), )); } } - self.add_value_rlp( - "id", - Bytes::copy_from_slice(&alloy_rlp::encode(self.id.as_bytes())), - ); + let mut id_bytes = BytesMut::with_capacity(3); + self.id.as_bytes().encode(&mut id_bytes); + self.add_value_rlp("id", id_bytes.freeze()); self.add_public_key(&key.public()); let rlp_content = self.rlp_content(); diff --git a/src/keys/ed25519.rs b/src/keys/ed25519.rs index 0bdfc0d..8603417 100644 --- a/src/keys/ed25519.rs +++ b/src/keys/ed25519.rs @@ -33,7 +33,7 @@ impl EnrKey for ed25519::SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.as_ref())?; Self::decode_public(&pubkey_bytes) } diff --git a/src/keys/k256_key.rs b/src/keys/k256_key.rs index a6ca010..6e58116 100644 --- a/src/keys/k256_key.rs +++ b/src/keys/k256_key.rs @@ -46,7 +46,7 @@ impl EnrKey for SigningKey { .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.as_ref())?; Self::decode_public(&pubkey_bytes) } diff --git a/src/keys/rust_secp256k1.rs b/src/keys/rust_secp256k1.rs index de9291c..70a1265 100644 --- a/src/keys/rust_secp256k1.rs +++ b/src/keys/rust_secp256k1.rs @@ -40,7 +40,7 @@ impl EnrKey for secp256k1::SecretKey { .get(ENR_KEY.as_bytes()) .ok_or(DecoderError::Custom("Unknown signature"))?; // Decode the RLP - let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.to_vec().as_slice())?; + let pubkey_bytes = Bytes::decode(&mut pubkey_bytes.as_ref())?; Self::decode_public(&pubkey_bytes) } diff --git a/src/lib.rs b/src/lib.rs index 39a1829..60ee409 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,7 +109,7 @@ //! //! enr.set_tcp4(8001, &key); //! // set a custom key -//! enr.insert("custom_key", &vec![0,0,1].as_slice(), &key); +//! enr.insert("custom_key", &[0,0,1], &key); //! //! // encode to base64 //! let base_64_string = enr.to_base64(); @@ -260,7 +260,7 @@ impl Enr { /// Will panic if data is not sanitized /// Reads a custom key from the record if it exists, decoded as data. #[allow(clippy::missing_panics_doc)] - pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { + pub fn get(&self, key: impl AsRef<[u8]>) -> Option { // It's ok to decode any valid RLP value as data self.get_raw_rlp(key) .map(|mut rlp_data| Bytes::decode(&mut rlp_data).expect("All data is sanitized")) @@ -506,9 +506,7 @@ impl Enr { let public_key = enr_key.public(); let mut pubkey = BytesMut::new(); public_key.encode().as_ref().encode(&mut pubkey); - let previous_key = self - .content - .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); + let previous_key = self.content.insert(public_key.enr_key(), pubkey.freeze()); // check the size of the record if self.size() > MAX_ENR_SIZE { @@ -578,7 +576,7 @@ impl Enr { /// Sets the `udp` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp4(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp", &udp, key)? { - return Ok(u16::decode(&mut udp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut udp_bytes.as_ref()).ok()); } Ok(None) } @@ -586,7 +584,7 @@ impl Enr { /// Sets the `udp6` field of the ENR. Returns any pre-existing UDP port in the record. pub fn set_udp6(&mut self, udp: u16, key: &K) -> Result, EnrError> { if let Some(udp_bytes) = self.insert("udp6", &udp, key)? { - return Ok(u16::decode(&mut udp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut udp_bytes.as_ref()).ok()); } Ok(None) } @@ -594,7 +592,7 @@ impl Enr { /// Sets the `tcp` field of the ENR. Returns any pre-existing tcp port in the record. pub fn set_tcp4(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp", &tcp, key)? { - return Ok(u16::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut tcp_bytes.as_ref()).ok()); } Ok(None) } @@ -602,7 +600,7 @@ impl Enr { /// Sets the `tcp6` field of the ENR. Returns any pre-existing tcp6 port in the record. pub fn set_tcp6(&mut self, tcp: u16, key: &K) -> Result, EnrError> { if let Some(tcp_bytes) = self.insert("tcp6", &tcp, key)? { - return Ok(u16::decode(&mut tcp_bytes.to_vec().as_slice()).ok()); + return Ok(u16::decode(&mut tcp_bytes.as_ref()).ok()); } Ok(None) } @@ -632,10 +630,8 @@ impl Enr { let mut port = BytesMut::new(); socket.port().encode(&mut port); ( - self.content - .insert("ip".into(), Bytes::copy_from_slice(&ip)), - self.content - .insert(port_string.clone(), Bytes::copy_from_slice(&port)), + self.content.insert("ip".into(), ip.freeze()), + self.content.insert(port_string.clone(), port.freeze()), ) } IpAddr::V6(addr) => { @@ -644,10 +640,8 @@ impl Enr { let mut port = BytesMut::new(); socket.port().encode(&mut port); ( - self.content - .insert("ip6".into(), Bytes::copy_from_slice(&ip6)), - self.content - .insert(port_v6_string.clone(), Bytes::copy_from_slice(&port)), + self.content.insert("ip6".into(), ip6.freeze()), + self.content.insert(port_v6_string.clone(), port.freeze()), ) } }; @@ -655,9 +649,7 @@ impl Enr { let public_key = key.public(); let mut pubkey = BytesMut::new(); public_key.encode().as_ref().encode(&mut pubkey); - let previous_key = self - .content - .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); + let previous_key = self.content.insert(public_key.enr_key(), pubkey.freeze()); // check the size and revert on failure if self.size() > MAX_ENR_SIZE { @@ -736,8 +728,7 @@ impl Enr { let public_key = enr_key.public(); let mut pubkey = BytesMut::new(); public_key.encode().as_ref().encode(&mut pubkey); - self.content - .insert(public_key.enr_key(), Bytes::copy_from_slice(&pubkey)); + self.content.insert(public_key.enr_key(), pubkey.freeze()); let mut inserted = Vec::new(); for (key, value) in insert_key_values { @@ -748,10 +739,10 @@ impl Enr { } let mut out = BytesMut::new(); value.encode(&mut out); - let value = Bytes::copy_from_slice(&out); + let value = out.freeze(); // Prevent inserting invalid RLP integers if is_keyof_u16(key.as_ref()) { - u16::decode(&mut value.to_vec().as_slice()) + u16::decode(&mut value.as_ref()) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; } From 9151474e67c97c355014c88c977c3f3c9c29e792 Mon Sep 17 00:00:00 2001 From: armaganyildirak Date: Fri, 20 Oct 2023 11:40:21 -0400 Subject: [PATCH 19/19] changes after review --- src/lib.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3d2ab02..8816e60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -264,9 +264,6 @@ impl Enr { self.seq } - /// # Panics - /// - /// Will panic if data is not sanitized /// Reads a custom key from the record if it exists, decoded as data. #[allow(clippy::missing_panics_doc)] pub fn get(&self, key: impl AsRef<[u8]>) -> Option { @@ -408,9 +405,7 @@ impl Enr { pub fn signature(&self) -> &[u8] { &self.signature } - /// # Panics - /// - /// Will panic if the content does not has a public key + /// Returns the public key of the ENR record. /// # Panics /// @@ -803,7 +798,7 @@ impl Enr { /// Encodes the ENR's content (signature(optional) + sequence number + ordered (key, value) pairs) into the stream. fn append_rlp_content(&self, stream: &mut BytesMut, include_signature: bool) { if include_signature { - self.signature.encode(stream); + self.signature.as_slice().encode(stream); } self.seq.encode(stream); for (k, v) in &self.content { @@ -968,19 +963,15 @@ impl<'de, K: EnrKey> Deserialize<'de> for Enr { impl Encodable for Enr { fn encode(&self, out: &mut dyn bytes::BufMut) { - let mut list = Vec::::new(); - self.signature.as_slice().encode(&mut list); - self.seq.encode(&mut list); - for (k, v) in &self.content { - k.as_slice().encode(&mut list); - list.extend_from_slice(v); - } + let mut stream = BytesMut::with_capacity(MAX_ENR_SIZE); + let include_signature = true; + self.append_rlp_content(&mut stream, include_signature); let header = Header { list: true, - payload_length: list.len(), + payload_length: stream.len(), }; header.encode(out); - out.put_slice(&list); + out.put_slice(&stream); } } @@ -996,6 +987,10 @@ impl Decodable for Enr { return Err(DecoderError::Custom("Invalid format of header")); } + if header.payload_length > buf.len() { + return Err(DecoderError::Custom("payload length exceeds buffer size")); + } + let payload = &mut &buf[..header.payload_length]; if payload.is_empty() { return Err(DecoderError::Custom("Payload is empty")); @@ -1132,7 +1127,7 @@ fn check_spec_reserved_keys(key: &[u8], mut value: &[u8]) -> Result<(), EnrError b"id" => { let id_bytes = Bytes::decode(&mut value) .map_err(|err| EnrError::InvalidRlpData(err.to_string()))?; - if id_bytes.to_vec() != b"v4" { + if id_bytes.as_ref() != b"v4" { return Err(EnrError::UnsupportedIdentityScheme); } }