reth_codecs/alloy/
access_list.rs

1//! Compact implementation for [`AccessList`]
2
3use crate::Compact;
4use alloc::vec::Vec;
5use alloy_eips::eip2930::{AccessList, AccessListItem};
6use alloy_primitives::Address;
7
8/// Implement `Compact` for `AccessListItem` and `AccessList`.
9impl Compact for AccessListItem {
10    fn to_compact<B>(&self, buf: &mut B) -> usize
11    where
12        B: bytes::BufMut + AsMut<[u8]>,
13    {
14        let mut buffer = Vec::new();
15        self.address.to_compact(&mut buffer);
16        self.storage_keys.specialized_to_compact(&mut buffer);
17        buf.put(&buffer[..]);
18        buffer.len()
19    }
20
21    fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
22        let (address, new_buf) = Address::from_compact(buf, buf.len());
23        buf = new_buf;
24        let (storage_keys, new_buf) = Vec::specialized_from_compact(buf, buf.len());
25        buf = new_buf;
26        let access_list_item = Self { address, storage_keys };
27        (access_list_item, buf)
28    }
29}
30
31impl Compact for AccessList {
32    fn to_compact<B>(&self, buf: &mut B) -> usize
33    where
34        B: bytes::BufMut + AsMut<[u8]>,
35    {
36        let mut buffer = Vec::new();
37        self.0.to_compact(&mut buffer);
38        buf.put(&buffer[..]);
39        buffer.len()
40    }
41
42    fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
43        let (access_list_items, new_buf) = Vec::from_compact(buf, buf.len());
44        buf = new_buf;
45        let access_list = Self(access_list_items);
46        (access_list, buf)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53    use alloy_primitives::Bytes;
54    use proptest::proptest;
55    use proptest_arbitrary_interop::arb;
56    use serde::Deserialize;
57
58    proptest! {
59        #[test]
60        fn test_roundtrip_compact_access_list_item(access_list_item in arb::<AccessListItem>()) {
61            let mut compacted_access_list_item = Vec::<u8>::new();
62            let len = access_list_item.to_compact(&mut compacted_access_list_item);
63
64            let (decoded_access_list_item, _) = AccessListItem::from_compact(&compacted_access_list_item, len);
65            assert_eq!(access_list_item, decoded_access_list_item);
66        }
67    }
68
69    proptest! {
70        #[test]
71        fn test_roundtrip_compact_access_list(access_list in arb::<AccessList>()) {
72            let mut compacted_access_list = Vec::<u8>::new();
73            let len = access_list.to_compact(&mut compacted_access_list);
74
75            let (decoded_access_list, _) = AccessList::from_compact(&compacted_access_list, len);
76            assert_eq!(access_list, decoded_access_list);
77        }
78    }
79
80    #[derive(Deserialize)]
81    struct CompactAccessListTestVector {
82        access_list: AccessList,
83        encoded_bytes: Bytes,
84    }
85
86    #[test]
87    fn test_compact_access_list_codec() {
88        let test_vectors: Vec<CompactAccessListTestVector> =
89            serde_json::from_str(include_str!("../../testdata/access_list_compact.json"))
90                .expect("Failed to parse test vectors");
91
92        for test_vector in test_vectors {
93            let mut buf = Vec::<u8>::new();
94            let len = test_vector.access_list.clone().to_compact(&mut buf);
95            assert_eq!(test_vector.encoded_bytes.0, buf);
96
97            let (decoded, _) = AccessList::from_compact(&test_vector.encoded_bytes, len);
98            assert_eq!(test_vector.access_list, decoded);
99        }
100    }
101}