diff --git a/CHANGELOG.md b/CHANGELOG.md index b013f22bd32..6f5c892b438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Perf +### 2025-11-20 + +- Improve rlp encoding by avoiding extra loops and remove unneeded array vec, also adding a alloc-less length method the default trait impl [#5350](https://github.com/lambdaclass/ethrex/pull/5350) + ### 2025-11-19 - Parallelize merkleization [#5377](https://github.com/lambdaclass/ethrex/pull/5377) diff --git a/crates/common/rlp/encode.rs b/crates/common/rlp/encode.rs index e420096f046..692eaaf004d 100644 --- a/crates/common/rlp/encode.rs +++ b/crates/common/rlp/encode.rs @@ -1,7 +1,6 @@ use bytes::{BufMut, Bytes}; use ethereum_types::U256; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use tinyvec::ArrayVec; use super::constants::RLP_NULL; @@ -13,13 +12,90 @@ pub fn encode(value: T) -> Vec { buf } +/// Calculates the encoded length of the given integer bit width (ilog2 value) and lsb +#[inline(always)] +const fn impl_length_integers(bits: u32, lsb: u8) -> usize { + // bits is the ilog2 0 based result, +8 accounts for the first byte boundary + let sig_len = (bits + 8) >> 3; + let is_multibyte_mask = ((sig_len > 1) as usize) | ((lsb > 0x7f) as usize); + 1 + sig_len as usize * is_multibyte_mask +} + +/// Computes the length needed for a given payload length +#[inline] +pub const fn list_length(payload_len: usize) -> usize { + if payload_len < 56 { + // short prefix + 1 + payload_len + } else { + // encode payload_len as big endian without leading zeros + let be_len = payload_len.ilog2() / 8 + 1; + // prefix + payload_len encoding size + payload bytes + 1 + be_len as usize + payload_len + } +} + +/// Computes the length needed for a given byte-string and first byte +#[inline] +pub const fn bytes_length(bytes_len: usize, first_byte: u8) -> usize { + if bytes_len == 1 && first_byte <= 0x7f { + return 1; + } + + if bytes_len < 56 { + return 1 + bytes_len; // prefix (0x80 + len) + payload + } + + // long (>=56 bytes) + let be_len = bytes_len.ilog2() / 8 + 1; + 1 + be_len as usize + bytes_len // prefix + len(len) + payload +} + +/// Struct implementing `BufMut`, but only counting the number of bytes pushed into the buffer. +#[derive(Debug, Clone, Copy, Default)] +struct ByteCounter { + count: usize, +} + +unsafe impl BufMut for ByteCounter { + fn remaining_mut(&self) -> usize { + usize::MAX - self.count + } + + unsafe fn advance_mut(&mut self, cnt: usize) { + self.count += cnt; + } + + fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice { + unreachable!( + "shouldn't be reachable since all the functions that call this are reimplemented" + ) + } + + fn put(&mut self, src: T) + where + Self: Sized, + { + self.count += src.remaining(); + } + + fn put_bytes(&mut self, _val: u8, cnt: usize) { + self.count += cnt; + } + + fn put_slice(&mut self, src: &[u8]) { + self.count += src.len() + } +} + pub trait RLPEncode { fn encode(&self, buf: &mut dyn BufMut); fn length(&self) -> usize { - let mut buf = Vec::new(); - self.encode(&mut buf); - buf.len() + // Run the `encode` function, but only counting the bytes pushed. + let mut counter = ByteCounter::default(); + self.encode(&mut counter); + counter.count } fn encode_to_vec(&self) -> Vec { @@ -47,76 +123,108 @@ impl RLPEncode for bool { // integer types impls +#[inline] fn impl_encode(value_be: [u8; N], buf: &mut dyn BufMut) { - let mut is_multi_byte_case = false; - - for n in value_be.iter().take(N - 1) { - // If we encounter a non 0 byte pattern before the last byte, we are - // at the multi byte case - if *n != 0 { - is_multi_byte_case = true; - break; - } + // count leading zeros + let mut i = 0; + while i < N && value_be[i] == 0 { + i += 1; } - match value_be[N - 1] { - // 0, also known as null or the empty string is 0x80 - 0 if !is_multi_byte_case => buf.put_u8(RLP_NULL), - // for a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding. - n @ 1..=0x7f if !is_multi_byte_case => buf.put_u8(n), - // if a string is 0-55 bytes long, the RLP encoding consists of a - // single byte with value RLP_NULL (0x80) plus the length of the string followed by the string. - _ => { - let mut bytes = ArrayVec::<[u8; 8]>::new(); - bytes.extend_from_slice(&value_be); - let start = bytes.iter().position(|&x| x != 0).unwrap(); - let len = bytes.len() - start; - buf.put_u8(RLP_NULL + len as u8); - buf.put_slice(&bytes[start..]); - } + // 0, also known as null or the empty string is 0x80 + if i == N { + buf.put_u8(RLP_NULL); + return; } + + let first = value_be[i]; + + // for a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding. + if i == N - 1 && first <= 0x7f { + buf.put_u8(first); + return; + } + + // if a string is 0-55 bytes long, the RLP encoding consists of a + // single byte with value RLP_NULL (0x80) plus the length of the string followed by the string. + let len = N - i; + buf.put_u8(RLP_NULL + len as u8); + buf.put_slice(&value_be[i..]); } impl RLPEncode for u8 { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), *self) + } } impl RLPEncode for u16 { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8) + } } impl RLPEncode for u32 { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8) + } } impl RLPEncode for u64 { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8) + } } impl RLPEncode for usize { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8) + } } impl RLPEncode for u128 { fn encode(&self, buf: &mut dyn BufMut) { impl_encode(self.to_be_bytes(), buf); } + + #[inline] + fn length(&self) -> usize { + impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8) + } } impl RLPEncode for () { fn encode(&self, buf: &mut dyn BufMut) { buf.put_u8(RLP_NULL); } + #[inline] + fn length(&self) -> usize { + 1 + } } impl RLPEncode for [u8] { @@ -129,8 +237,7 @@ impl RLPEncode for [u8] { if len < 56 { buf.put_u8(RLP_NULL + len as u8); } else { - let mut bytes = ArrayVec::<[u8; 8]>::new(); - bytes.extend_from_slice(&len.to_be_bytes()); + let bytes = len.to_be_bytes(); let start = bytes.iter().position(|&x| x != 0).unwrap(); let len = bytes.len() - start; buf.put_u8(0xb7 + len as u8); @@ -140,48 +247,76 @@ impl RLPEncode for [u8] { } } + #[inline] fn length(&self) -> usize { - const U8_MAX_PLUS_ONE: usize = u8::MAX as usize + 1; - const U16_MAX_PLUS_ONE: usize = u16::MAX as usize + 1; - - match self.len() { - 0 => 1, // encodes to RLP_NULL - 1 if self[0] < 0x80 => 1, // `self` is its own encoding - 1..56 => 1 + self.len(), // single byte prefix - 56..U8_MAX_PLUS_ONE => 1 + 1 + self.len(), // single byte prefix + payload len bytes - U8_MAX_PLUS_ONE..U16_MAX_PLUS_ONE => 1 + 2 + self.len(), // single byte prefix + payload len bytes - _ => { - // fallback if `self` is longer than 2^16 - 1 bytes - let payload_len_bytes = - ((usize::BITS - self.len().leading_zeros()) as usize).div_ceil(8); - 1 + payload_len_bytes + self.len() - } + if self.is_empty() { + return 1; } + bytes_length(self.len(), self[0]) } } impl RLPEncode for [u8; N] { + #[inline] fn encode(&self, buf: &mut dyn BufMut) { self.as_ref().encode(buf) } + + #[inline] + fn length(&self) -> usize { + if N == 1 && self[0] <= 0x7f { + return 1; + } + + if N < 56 { + return 1 + N; + } + + // long case + let be_len = if N == 0 { + 1 + } else { + (N.ilog2() as usize / 8) + 1 + }; + + 1 + be_len + N + } } impl RLPEncode for str { + #[inline] fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for &str { + #[inline] fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for String { + #[inline] fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for U256 { @@ -190,29 +325,51 @@ impl RLPEncode for U256 { let bytes = self.to_big_endian(); bytes[leading_zeros_in_bytes..].encode(buf) } + + fn length(&self) -> usize { + let ilog = self.bits().saturating_sub(1); + impl_length_integers(ilog as u32, (self.low_u32() & 0xff) as u8) + } } impl RLPEncode for Vec { + #[inline(always)] fn encode(&self, buf: &mut dyn BufMut) { if self.is_empty() { buf.put_u8(0xc0); } else { - let mut tmp_buf = vec![]; + let payload_len: usize = self.iter().map(|item| item.length()).sum(); + + encode_length(payload_len, buf); + for item in self { - item.encode(&mut tmp_buf); + item.encode(buf); } - encode_length(tmp_buf.len(), buf); - buf.put_slice(&tmp_buf); } } + + #[inline] + fn length(&self) -> usize { + if self.is_empty() { + // 0xc0 (1 byte) + return 1; + } + + let mut payload_len = 0usize; + for item in self { + payload_len += item.length(); + } + + list_length(payload_len) + } } +#[inline] pub fn encode_length(total_len: usize, buf: &mut dyn BufMut) { if total_len < 56 { buf.put_u8(0xc0 + total_len as u8); } else { - let mut bytes = ArrayVec::<[u8; 8]>::new(); - bytes.extend_from_slice(&total_len.to_be_bytes()); + let bytes = total_len.to_be_bytes(); let start = bytes.iter().position(|&x| x != 0).unwrap(); let len = bytes.len() - start; buf.put_u8(0xf7 + len as u8); @@ -227,6 +384,12 @@ impl RLPEncode for (S, T) { .encode_field(&self.1) .finish(); } + + #[inline] + fn length(&self) -> usize { + let payload_len = self.0.length() + self.1.length(); + list_length(payload_len) + } } impl RLPEncode for (S, T, U) { @@ -237,6 +400,12 @@ impl RLPEncode for (S, T, U) { .encode_field(&self.2) .finish(); } + + #[inline] + fn length(&self) -> usize { + let payload_len = self.0.length() + self.1.length() + self.2.length(); + list_length(payload_len) + } } impl RLPEncode for (S, T, U, V) { @@ -248,6 +417,12 @@ impl RLPEncode for (S, T .encode_field(&self.3) .finish(); } + + #[inline] + fn length(&self) -> usize { + let payload_len = self.0.length() + self.1.length() + self.2.length() + self.3.length(); + list_length(payload_len) + } } impl RLPEncode @@ -262,18 +437,35 @@ impl RLPEn .encode_field(&self.4) .finish(); } + + #[inline] + fn length(&self) -> usize { + let payload_len = + self.0.length() + self.1.length() + self.2.length() + self.3.length() + self.4.length(); + list_length(payload_len) + } } impl RLPEncode for Ipv4Addr { fn encode(&self, buf: &mut dyn BufMut) { self.octets().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(&self.octets()) + } } impl RLPEncode for Ipv6Addr { fn encode(&self, buf: &mut dyn BufMut) { self.octets().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(&self.octets()) + } } impl RLPEncode for IpAddr { @@ -283,12 +475,24 @@ impl RLPEncode for IpAddr { IpAddr::V6(ip) => ip.encode(buf), } } + + #[inline] + fn length(&self) -> usize { + match self { + IpAddr::V4(ipv4_addr) => RLPEncode::length(&ipv4_addr.octets()), + IpAddr::V6(ipv6_addr) => RLPEncode::length(&ipv6_addr.octets()), + } + } } impl RLPEncode for Bytes { fn encode(&self, buf: &mut dyn BufMut) { self.as_ref().encode(buf) } + + fn length(&self) -> usize { + self.as_ref().length() + } } // encoding for Ethereum types @@ -297,54 +501,99 @@ impl RLPEncode for ethereum_types::H32 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::H64 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::H128 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::Address { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::H256 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::H264 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::H512 { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::Signature { fn encode(&self, buf: &mut dyn BufMut) { self.as_bytes().encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(self.as_bytes()) + } } impl RLPEncode for ethereum_types::Bloom { fn encode(&self, buf: &mut dyn BufMut) { self.0.encode(buf) } + + #[inline] + fn length(&self) -> usize { + RLPEncode::length(&self.0) + } } pub trait PayloadRLPEncode { @@ -381,24 +630,29 @@ mod tests { #[test] fn can_encode_u32() { let mut encoded = Vec::new(); - 0u16.encode(&mut encoded); + 0u32.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL]); + assert_eq!(encoded.len(), 0u32.length()); let mut encoded = Vec::new(); - 1u16.encode(&mut encoded); + 1u32.encode(&mut encoded); assert_eq!(encoded, vec![0x01]); + assert_eq!(encoded.len(), 1u32.length()); let mut encoded = Vec::new(); - 0x7Fu16.encode(&mut encoded); + 0x7Fu32.encode(&mut encoded); assert_eq!(encoded, vec![0x7f]); + assert_eq!(encoded.len(), 0x7Fu32.length()); let mut encoded = Vec::new(); - 0x80u16.encode(&mut encoded); + 0x80u32.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x80]); + assert_eq!(encoded.len(), 0x80u32.length()); let mut encoded = Vec::new(); - 0x90u16.encode(&mut encoded); + 0x90u32.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x90]); + assert_eq!(encoded.len(), 0x90u32.length()); } #[test] @@ -406,22 +660,55 @@ mod tests { let mut encoded = Vec::new(); 0u16.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL]); + assert_eq!(encoded.len(), 0u16.length()); let mut encoded = Vec::new(); 1u16.encode(&mut encoded); assert_eq!(encoded, vec![0x01]); + assert_eq!(encoded.len(), 1u16.length()); let mut encoded = Vec::new(); 0x7Fu16.encode(&mut encoded); assert_eq!(encoded, vec![0x7f]); + assert_eq!(encoded.len(), 0x7Fu16.length()); let mut encoded = Vec::new(); 0x80u16.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x80]); + assert_eq!(encoded.len(), 0x80u16.length()); let mut encoded = Vec::new(); 0x90u16.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x90]); + assert_eq!(encoded.len(), 0x90u16.length()); + } + + #[test] + fn u16_length_matches() { + let mut encoded = Vec::new(); + 0x0100u16.encode(&mut encoded); + assert_eq!(encoded.len(), 0x0100u16.length(),); + } + + #[test] + fn u256_length_matches() { + let value = U256::from(0x0100u64); + let mut encoded = Vec::new(); + value.encode(&mut encoded); + assert_eq!(encoded.len(), value.length(),); + } + + #[test] + fn u64_lengths_match() { + for n in 0u64..=10_000 { + let mut encoded = Vec::new(); + n.encode(&mut encoded); + assert_eq!( + encoded.len(), + n.length(), + "u64 length mismatch at value {n}" + ); + } } #[test] @@ -429,68 +716,83 @@ mod tests { let mut encoded = Vec::new(); 0u8.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL]); + assert_eq!(encoded.len(), 0u8.length()); let mut encoded = Vec::new(); 1u8.encode(&mut encoded); assert_eq!(encoded, vec![0x01]); + assert_eq!(encoded.len(), 1u8.length()); let mut encoded = Vec::new(); 0x7Fu8.encode(&mut encoded); assert_eq!(encoded, vec![0x7f]); + assert_eq!(encoded.len(), 0x7Fu8.length()); let mut encoded = Vec::new(); 0x80u8.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x80]); + assert_eq!(encoded.len(), 0x80u8.length()); let mut encoded = Vec::new(); 0x90u8.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x90]); + assert_eq!(encoded.len(), 0x90u8.length()); } #[test] fn can_encode_u64() { let mut encoded = Vec::new(); - 0u8.encode(&mut encoded); + 0u64.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL]); + assert_eq!(encoded.len(), 0u64.length()); let mut encoded = Vec::new(); - 1u8.encode(&mut encoded); + 1u64.encode(&mut encoded); assert_eq!(encoded, vec![0x01]); + assert_eq!(encoded.len(), 1u64.length()); let mut encoded = Vec::new(); - 0x7Fu8.encode(&mut encoded); + 0x7Fu64.encode(&mut encoded); assert_eq!(encoded, vec![0x7f]); + assert_eq!(encoded.len(), 0x7Fu64.length()); let mut encoded = Vec::new(); - 0x80u8.encode(&mut encoded); + 0x80u64.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x80]); + assert_eq!(encoded.len(), 0x80u64.length()); let mut encoded = Vec::new(); - 0x90u8.encode(&mut encoded); + 0x90u64.encode(&mut encoded); assert_eq!(encoded, vec![RLP_NULL + 1, 0x90]); + assert_eq!(encoded.len(), 0x90u64.length()); } #[test] fn can_encode_usize() { let mut encoded = Vec::new(); - 0u8.encode(&mut encoded); + 0usize.encode(&mut encoded); assert_eq!(encoded, vec![0x80]); + assert_eq!(encoded.len(), 0usize.length()); let mut encoded = Vec::new(); - 1u8.encode(&mut encoded); + 1usize.encode(&mut encoded); assert_eq!(encoded, vec![0x01]); + assert_eq!(encoded.len(), 1usize.length()); let mut encoded = Vec::new(); - 0x7Fu8.encode(&mut encoded); + 0x7Fusize.encode(&mut encoded); assert_eq!(encoded, vec![0x7f]); + assert_eq!(encoded.len(), 0x7Fusize.length()); let mut encoded = Vec::new(); - 0x80u8.encode(&mut encoded); + 0x80usize.encode(&mut encoded); assert_eq!(encoded, vec![0x80 + 1, 0x80]); + assert_eq!(encoded.len(), 0x80usize.length()); let mut encoded = Vec::new(); - 0x90u8.encode(&mut encoded); + 0x90usize.encode(&mut encoded); assert_eq!(encoded, vec![0x80 + 1, 0x90]); + assert_eq!(encoded.len(), 0x90usize.length()); } #[test] @@ -503,6 +805,7 @@ mod tests { buf }; assert_eq!(encoded, vec![0x00]); + assert_eq!(encoded.len(), message.length()); // encode byte 0x0f let message: [u8; 1] = [0x0f]; @@ -512,6 +815,7 @@ mod tests { buf }; assert_eq!(encoded, vec![0x0f]); + assert_eq!(encoded.len(), message.length()); // encode bytes '\x04\x00' let message: [u8; 2] = [0x04, 0x00]; @@ -521,6 +825,7 @@ mod tests { buf }; assert_eq!(encoded, vec![RLP_NULL + 2, 0x04, 0x00]); + assert_eq!(encoded.len(), message.length()); } #[test] @@ -534,6 +839,7 @@ mod tests { }; let expected: [u8; 4] = [RLP_NULL + 3, b'd', b'o', b'g']; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), message.length()); // encode empty string let message = ""; @@ -544,6 +850,7 @@ mod tests { }; let expected: [u8; 1] = [RLP_NULL]; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), message.length()); } #[test] @@ -557,6 +864,7 @@ mod tests { }; let expected: [u8; 9] = [0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), message.length()); // encode empty list let message: Vec<&str> = vec![]; @@ -567,6 +875,7 @@ mod tests { }; let expected: [u8; 1] = [RLP_EMPTY_LIST]; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), message.length()); } #[test] @@ -581,6 +890,7 @@ mod tests { }; let expected: [u8; 5] = [RLP_NULL + 4, 192, 168, 0, 1]; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), ip.length()); // encode an IPv6 address let message = "2001:0000:130F:0000:0000:09C0:876A:130B"; @@ -595,6 +905,7 @@ mod tests { 0x6a, 0x13, 0x0b, ]; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), ip.length()); } #[test] @@ -607,6 +918,7 @@ mod tests { }; let expected = hex!("94ef2d6d194084c2de36e0dabfce45d046b37d1106"); assert_eq!(encoded, expected); + assert_eq!(encoded.len(), address.length()); } #[test] @@ -614,10 +926,12 @@ mod tests { let mut encoded = Vec::new(); U256::from(1).encode(&mut encoded); assert_eq!(encoded, vec![1]); + assert_eq!(encoded.len(), U256::from(1).length()); let mut encoded = Vec::new(); U256::from(128).encode(&mut encoded); assert_eq!(encoded, vec![0x80 + 1, 128]); + assert_eq!(encoded.len(), U256::from(128).length()); let mut encoded = Vec::new(); U256::max_value().encode(&mut encoded); @@ -625,6 +939,7 @@ mod tests { let mut expected: Vec = bytes.into(); expected.insert(0, 0x80 + 32); assert_eq!(encoded, expected); + assert_eq!(encoded.len(), U256::max_value().length()); } #[test] @@ -635,5 +950,6 @@ mod tests { tuple.encode(&mut encoded); let expected = vec![0xc0 + 2, 0x01, 0x02]; assert_eq!(encoded, expected); + assert_eq!(encoded.len(), tuple.length()); } } diff --git a/tooling/Cargo.lock b/tooling/Cargo.lock index 3355bd940af..fceb0ba508c 100644 --- a/tooling/Cargo.lock +++ b/tooling/Cargo.lock @@ -310,10 +310,10 @@ dependencies = [ "clap 4.5.51", "clap_complete", "ethrex", - "ethrex-common 6.0.0", - "ethrex-rlp 6.0.0", + "ethrex-common 7.0.0", + "ethrex-rlp 7.0.0", "ethrex-rpc", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "eyre", "hex", "lazy_static", @@ -2569,10 +2569,10 @@ dependencies = [ "bytes", "datatest-stable", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-prover", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", "ethrex-vm", "guest_program", "hex", @@ -2593,10 +2593,10 @@ dependencies = [ "clap_complete", "colored", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-levm", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", "ethrex-vm", "hex", "itertools 0.13.0", @@ -2621,11 +2621,11 @@ dependencies = [ "clap_complete", "colored", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2-rpc", "ethrex-levm", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", "ethrex-vm", "hex", "prettytable-rs", @@ -3168,7 +3168,7 @@ dependencies = [ [[package]] name = "ethrex" -version = "6.0.0" +version = "7.0.0" dependencies = [ "anyhow", "bytes", @@ -3176,7 +3176,7 @@ dependencies = [ "clap_complete", "directories", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-config", "ethrex-crypto", "ethrex-dev", @@ -3186,10 +3186,10 @@ dependencies = [ "ethrex-metrics", "ethrex-p2p", "ethrex-prover", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-rpc", "ethrex-sdk", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "ethrex-storage-rollup", "ethrex-vm", "eyre", @@ -3218,19 +3218,18 @@ dependencies = [ [[package]] name = "ethrex-blockchain" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", "ethrex-metrics", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", + "ethrex-trie 7.0.0", "ethrex-vm", "hex", "rustc-hash 2.1.1", - "secp256k1 0.30.0", "thiserror 2.0.17", "tokio", "tokio-util", @@ -3266,15 +3265,16 @@ dependencies = [ [[package]] name = "ethrex-common" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "crc32fast", "ethereum-types 0.15.1", "ethrex-crypto", - "ethrex-rlp 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-trie 7.0.0", "hex", + "k256 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", "kzg-rs", "lazy_static", "libc", @@ -3286,6 +3286,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", + "sha3", "thiserror 2.0.17", "tinyvec", "tracing", @@ -3294,9 +3295,9 @@ dependencies = [ [[package]] name = "ethrex-config" -version = "6.0.0" +version = "7.0.0" dependencies = [ - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-p2p", "hex", "serde", @@ -3305,7 +3306,7 @@ dependencies = [ [[package]] name = "ethrex-crypto" -version = "6.0.0" +version = "7.0.0" dependencies = [ "c-kzg", "kzg-rs", @@ -3315,7 +3316,7 @@ dependencies = [ [[package]] name = "ethrex-dev" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "envy", @@ -3334,7 +3335,7 @@ dependencies = [ [[package]] name = "ethrex-l2" -version = "6.0.0" +version = "7.0.0" dependencies = [ "aligned-sdk", "axum 0.8.6", @@ -3349,7 +3350,7 @@ dependencies = [ "ethereum-types 0.15.1", "ethers", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-config", "ethrex-dev", "ethrex-l2-common", @@ -3357,12 +3358,12 @@ dependencies = [ "ethrex-levm", "ethrex-metrics", "ethrex-p2p", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-rpc", "ethrex-sdk", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "ethrex-storage-rollup", - "ethrex-trie 6.0.0", + "ethrex-trie 7.0.0", "ethrex-vm", "futures", "guest_program", @@ -3391,39 +3392,41 @@ dependencies = [ [[package]] name = "ethrex-l2-common" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "ethereum-types 0.15.1", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", + "ethrex-trie 7.0.0", "ethrex-vm", "hex", + "k256 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", "lambdaworks-crypto 0.13.0", "rkyv", "secp256k1 0.30.0", "serde", "serde_with", + "sha3", "thiserror 2.0.17", ] [[package]] name = "ethrex-l2-rpc" -version = "6.0.0" +version = "7.0.0" dependencies = [ "axum 0.8.6", "bytes", "ethereum-types 0.15.1", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2-common", "ethrex-p2p", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-rpc", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "ethrex-storage-rollup", "hex", "reqwest 0.12.24", @@ -3441,7 +3444,7 @@ dependencies = [ [[package]] name = "ethrex-levm" -version = "6.0.0" +version = "7.0.0" dependencies = [ "ark-bn254", "ark-ec", @@ -3451,9 +3454,9 @@ dependencies = [ "bytes", "datatest-stable", "derive_more 1.0.0", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "k256 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", "lambdaworks-math 0.13.0", "lazy_static", @@ -3465,6 +3468,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", + "sha3", "strum 0.27.2", "thiserror 2.0.17", "walkdir", @@ -3472,10 +3476,10 @@ dependencies = [ [[package]] name = "ethrex-metrics" -version = "6.0.0" +version = "7.0.0" dependencies = [ "axum 0.8.6", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "prometheus 0.13.4", "serde", "serde_json", @@ -3487,7 +3491,7 @@ dependencies = [ [[package]] name = "ethrex-p2p" -version = "6.0.0" +version = "7.0.0" dependencies = [ "aes", "async-trait", @@ -3497,13 +3501,13 @@ dependencies = [ "ctr", "ethereum-types 0.15.1", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", "ethrex-storage-rollup", "ethrex-threadpool", - "ethrex-trie 6.0.0", + "ethrex-trie 7.0.0", "futures", "hex", "hmac", @@ -3529,7 +3533,7 @@ dependencies = [ [[package]] name = "ethrex-prover" -version = "6.0.0" +version = "7.0.0" dependencies = [ "anyhow", "bincode", @@ -3537,12 +3541,12 @@ dependencies = [ "clap 4.5.51", "ethereum-types 0.15.1", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2", "ethrex-l2-common", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-sdk", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "ethrex-vm", "guest_program", "hex", @@ -3576,7 +3580,7 @@ dependencies = [ [[package]] name = "ethrex-rlp" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "ethereum-types 0.15.1", @@ -3589,7 +3593,7 @@ dependencies = [ [[package]] name = "ethrex-rpc" -version = "6.0.0" +version = "7.0.0" dependencies = [ "axum 0.8.6", "axum-extra", @@ -3597,12 +3601,13 @@ dependencies = [ "envy", "ethereum-types 0.15.1", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", + "ethrex-metrics", "ethrex-p2p", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", + "ethrex-trie 7.0.0", "ethrex-vm", "hex", "hex-literal", @@ -3626,14 +3631,14 @@ dependencies = [ [[package]] name = "ethrex-sdk" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "ethereum-types 0.15.1", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2-common", "ethrex-l2-rpc", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-rpc", "ethrex-sdk-contract-utils", "eyre", @@ -3651,7 +3656,7 @@ dependencies = [ [[package]] name = "ethrex-sdk-contract-utils" -version = "6.0.0" +version = "7.0.0" dependencies = [ "thiserror 2.0.17", "tracing", @@ -3682,18 +3687,19 @@ dependencies = [ [[package]] name = "ethrex-storage" -version = "6.0.0" +version = "7.0.0" dependencies = [ "anyhow", "async-trait", "bincode", "bytes", "ethereum-types 0.15.1", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", - "ethrex-rlp 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-trie 7.0.0", "hex", + "lru 0.16.2", "qfilter", "rayon", "rocksdb", @@ -3707,17 +3713,17 @@ dependencies = [ [[package]] name = "ethrex-storage-rollup" -version = "6.0.0" +version = "7.0.0" dependencies = [ "anyhow", "async-trait", "bincode", "ethereum-types 0.15.1", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2-common", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", + "ethrex-trie 7.0.0", "futures", "rkyv", "thiserror 2.0.17", @@ -3754,7 +3760,7 @@ dependencies = [ [[package]] name = "ethrex-trie" -version = "6.0.0" +version = "7.0.0" dependencies = [ "anyhow", "bytes", @@ -3762,7 +3768,7 @@ dependencies = [ "digest 0.10.7", "ethereum-types 0.15.1", "ethrex-crypto", - "ethrex-rlp 6.0.0", + "ethrex-rlp 7.0.0", "ethrex-threadpool", "hex", "lazy_static", @@ -3778,19 +3784,18 @@ dependencies = [ [[package]] name = "ethrex-vm" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bincode", "bytes", "derive_more 1.0.0", "dyn-clone", "ethereum-types 0.15.1", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", "ethrex-levm", - "ethrex-rlp 6.0.0", - "ethrex-trie 6.0.0", - "hex", + "ethrex-rlp 7.0.0", + "ethrex-trie 7.0.0", "lazy_static", "rkyv", "serde", @@ -4302,16 +4307,16 @@ dependencies = [ [[package]] name = "guest_program" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bytes", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-crypto", "ethrex-l2-common", - "ethrex-rlp 6.0.0", - "ethrex-storage 6.0.0", - "ethrex-trie 6.0.0", + "ethrex-rlp 7.0.0", + "ethrex-storage 7.0.0", + "ethrex-trie 7.0.0", "ethrex-vm", "hex", "rkyv", @@ -4439,6 +4444,8 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.2.0", "serde", ] @@ -5454,6 +5461,7 @@ dependencies = [ "cc", "libc", "libz-sys", + "lz4-sys", ] [[package]] @@ -5557,7 +5565,7 @@ dependencies = [ "clap 4.5.51", "ethereum-types 0.15.1", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-l2-common", "ethrex-l2-rpc", "ethrex-rpc", @@ -5620,12 +5628,31 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "lru" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +dependencies = [ + "hashbrown 0.16.0", +] + [[package]] name = "lru-slab" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "malachite" version = "0.6.1" @@ -5757,9 +5784,9 @@ dependencies = [ "clap 4.5.51", "ethrex-blockchain", "ethrex-common 1.0.0", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-storage 1.0.0", - "ethrex-storage 6.0.0", + "ethrex-storage 7.0.0", "tokio", ] @@ -7336,7 +7363,7 @@ dependencies = [ "indoc", "instability", "itertools 0.13.0", - "lru", + "lru 0.12.5", "paste", "strum 0.26.3", "unicode-segmentation", @@ -7466,7 +7493,7 @@ version = "4.0.0" dependencies = [ "ethrex", "ethrex-blockchain", - "ethrex-common 6.0.0", + "ethrex-common 7.0.0", "ethrex-config", "ethrex-l2-common", "ethrex-l2-rpc", @@ -9027,7 +9054,7 @@ dependencies = [ "hashbrown 0.14.5", "hex", "itertools 0.13.0", - "lru", + "lru 0.12.5", "num-bigint 0.4.6", "p3-baby-bear", "p3-bn254-fr",