mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Implement Compact codec for alloy_primitives::Log (#7474)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -6237,6 +6237,7 @@ dependencies = [
|
||||
"proptest-derive",
|
||||
"reth-codecs-derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"test-fuzz",
|
||||
]
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ alloy-eips.workspace = true
|
||||
enr = { workspace = true, features = ["rust-secp256k1"] }
|
||||
|
||||
# crypto
|
||||
secp256k1 = { workspace = true, features = ["global-context", "recovery"] }
|
||||
secp256k1 = { workspace = true, features = ["global-context", "recovery", "rand"] }
|
||||
# for eip-4844
|
||||
c-kzg = { workspace = true, features = ["serde"], optional = true }
|
||||
|
||||
|
||||
@ -51,3 +51,27 @@ where
|
||||
}
|
||||
bloom
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use proptest::proptest;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn test_roundtrip_conversion_between_log_and_alloy_log(log: Log) {
|
||||
// Convert log to buffer and then create alloy_log from buffer and compare
|
||||
let mut compacted_log = Vec::<u8>::new();
|
||||
let len = log.clone().to_compact(&mut compacted_log);
|
||||
|
||||
let alloy_log = AlloyLog::from_compact(&compacted_log, len).0;
|
||||
assert_eq!(log, alloy_log.into());
|
||||
|
||||
// Create alloy_log from log and then convert it to buffer and compare compacted_alloy_log and compacted_log
|
||||
let alloy_log = AlloyLog::new_unchecked(log.address, log.topics, log.data);
|
||||
let mut compacted_alloy_log = Vec::<u8>::new();
|
||||
let _len = alloy_log.to_compact(&mut compacted_alloy_log);
|
||||
assert_eq!(compacted_log, compacted_alloy_log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ alloy-primitives = { workspace = true, features = ["arbitrary", "serde"] }
|
||||
serde.workspace = true
|
||||
modular-bitfield = "0.11.2"
|
||||
test-fuzz.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
arbitrary = { workspace = true, features = ["derive"] }
|
||||
proptest.workspace = true
|
||||
|
||||
94
crates/storage/codecs/src/alloy/log.rs
Normal file
94
crates/storage/codecs/src/alloy/log.rs
Normal file
@ -0,0 +1,94 @@
|
||||
use crate::Compact;
|
||||
use alloy_primitives::{Address, Bytes, Log, LogData};
|
||||
use bytes::BufMut;
|
||||
|
||||
/// Implement `Compact` for `LogData` and `Log`.
|
||||
impl Compact for LogData {
|
||||
fn to_compact<B>(self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>,
|
||||
{
|
||||
let mut buffer = bytes::BytesMut::new();
|
||||
let (topics, data) = self.split();
|
||||
topics.specialized_to_compact(&mut buffer);
|
||||
data.to_compact(&mut buffer);
|
||||
let total_length = buffer.len();
|
||||
buf.put(buffer);
|
||||
total_length
|
||||
}
|
||||
|
||||
fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
|
||||
let (topics, new_buf) = Vec::specialized_from_compact(buf, buf.len());
|
||||
buf = new_buf;
|
||||
let (data, buf) = Bytes::from_compact(buf, buf.len());
|
||||
let log_data = LogData::new_unchecked(topics, data);
|
||||
(log_data, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Compact for Log {
|
||||
fn to_compact<B>(self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>,
|
||||
{
|
||||
let mut buffer = bytes::BytesMut::new();
|
||||
self.address.to_compact(&mut buffer);
|
||||
self.data.to_compact(&mut buffer);
|
||||
let total_length = buffer.len();
|
||||
buf.put(buffer);
|
||||
total_length
|
||||
}
|
||||
|
||||
fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
|
||||
let (address, new_buf) = Address::from_compact(buf, buf.len());
|
||||
buf = new_buf;
|
||||
let (log_data, new_buf) = LogData::from_compact(buf, buf.len());
|
||||
buf = new_buf;
|
||||
let log = Log { address, data: log_data };
|
||||
(log, buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Compact, Log};
|
||||
use alloy_primitives::{Address, Bytes, LogData, B256};
|
||||
use proptest::proptest;
|
||||
use serde::Deserialize;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn roundtrip(log: Log) {
|
||||
let mut buf = Vec::<u8>::new();
|
||||
let len = log.clone().to_compact(&mut buf);
|
||||
let (decoded, _) = Log::from_compact(&buf, len);
|
||||
assert_eq!(log, decoded);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CompactLogTestVector {
|
||||
topics: Vec<B256>,
|
||||
address: Address,
|
||||
data: Bytes,
|
||||
encoded_bytes: Bytes,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compact_log_codec() {
|
||||
let test_vectors: Vec<CompactLogTestVector> =
|
||||
serde_json::from_str(include_str!("../../testdata/log_compact.json")).unwrap();
|
||||
|
||||
for test_vector in test_vectors {
|
||||
let log_data = LogData::new_unchecked(test_vector.topics, test_vector.data);
|
||||
let log = Log { address: test_vector.address, data: log_data };
|
||||
|
||||
let mut buf = Vec::<u8>::new();
|
||||
let len = log.clone().to_compact(&mut buf);
|
||||
assert_eq!(test_vector.encoded_bytes, buf);
|
||||
|
||||
let (decoded, _) = Log::from_compact(&test_vector.encoded_bytes, len);
|
||||
assert_eq!(log, decoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
crates/storage/codecs/src/alloy/mod.rs
Normal file
1
crates/storage/codecs/src/alloy/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
mod log;
|
||||
@ -16,6 +16,8 @@ pub use reth_codecs_derive::*;
|
||||
use alloy_primitives::{Address, Bloom, Bytes, B256, B512, U256};
|
||||
use bytes::Buf;
|
||||
|
||||
mod alloy;
|
||||
|
||||
/// Trait that implements the `Compact` codec.
|
||||
///
|
||||
/// When deriving the trait for custom structs, be aware of certain limitations/recommendations:
|
||||
|
||||
2397
crates/storage/codecs/testdata/log_compact.json
vendored
Normal file
2397
crates/storage/codecs/testdata/log_compact.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user