arbos/address_table/
mod.rs1use alloy_primitives::{Address, B256, U256};
2use alloy_rlp::{Decodable, Encodable};
3use revm::Database;
4
5use arb_storage::{Storage, StorageBackedUint64};
6
7pub struct AddressTable<D> {
13 backing_storage: Storage<D>,
14 by_address: Storage<D>,
15 num_items: StorageBackedUint64<D>,
16}
17
18pub fn initialize_address_table<D: Database>(_sto: &Storage<D>) {
19 }
21
22pub fn open_address_table<D: Database>(sto: Storage<D>) -> AddressTable<D> {
23 let num_items = StorageBackedUint64::new(sto.state_ptr(), sto.base_key(), 0);
24 let by_address = sto.open_sub_storage(&[]);
25 AddressTable {
26 backing_storage: sto,
27 by_address,
28 num_items,
29 }
30}
31
32impl<D: Database> AddressTable<D> {
33 pub fn register(&self, addr: Address) -> Result<u64, ()> {
34 let addr_hash = address_to_hash(addr);
35 let rev = self.by_address.get(addr_hash)?;
36
37 if rev != B256::ZERO {
38 return Ok(U256::from_be_bytes(rev.0).to::<u64>() - 1);
39 }
40
41 let current = self.num_items.get()?;
43 let new_num_items = current + 1;
44 self.num_items.set(new_num_items)?;
45
46 self.backing_storage
47 .set_by_uint64(new_num_items, addr_hash)?;
48 self.by_address
49 .set(addr_hash, uint_to_hash(new_num_items))?;
50
51 Ok(new_num_items - 1)
52 }
53
54 pub fn lookup(&self, addr: Address) -> Result<(u64, bool), ()> {
55 let addr_hash = address_to_hash(addr);
56 let res_hash = self.by_address.get(addr_hash)?;
57 let res = U256::from_be_bytes(res_hash.0).to::<u64>();
58
59 if res == 0 {
60 Ok((0, false))
61 } else {
62 Ok((res - 1, true))
63 }
64 }
65
66 pub fn address_exists(&self, addr: Address) -> Result<bool, ()> {
67 let (_, exists) = self.lookup(addr)?;
68 Ok(exists)
69 }
70
71 pub fn size(&self) -> Result<u64, ()> {
72 self.num_items.get()
73 }
74
75 pub fn lookup_index(&self, index: u64) -> Result<Option<Address>, ()> {
76 let items = self.num_items.get()?;
77 if index >= items {
78 return Ok(None);
79 }
80 let value = self.backing_storage.get_by_uint64(index + 1)?;
81 let mut addr_bytes = [0u8; 20];
82 addr_bytes.copy_from_slice(&value.0[12..32]);
83 Ok(Some(Address::from(addr_bytes)))
84 }
85
86 pub fn compress(&self, addr: Address) -> Result<Vec<u8>, ()> {
88 let (index, exists) = self.lookup(addr)?;
89 if exists {
90 let mut buf = Vec::new();
91 index.encode(&mut buf);
92 Ok(buf)
93 } else {
94 let mut buf = Vec::new();
95 addr.as_slice().encode(&mut buf);
96 Ok(buf)
97 }
98 }
99
100 pub fn decompress(&self, buf: &[u8]) -> Result<(Address, u64), ()> {
103 let mut cursor = buf;
105 let input = <Vec<u8> as Decodable>::decode(&mut cursor).map_err(|_| ())?;
106 let bytes_read = (buf.len() - cursor.len()) as u64;
107
108 if input.len() == 20 {
109 let mut addr_bytes = [0u8; 20];
110 addr_bytes.copy_from_slice(&input);
111 Ok((Address::from(addr_bytes), bytes_read))
112 } else {
113 let mut cursor = buf;
115 let index = u64::decode(&mut cursor).map_err(|_| ())?;
116 let bytes_read = (buf.len() - cursor.len()) as u64;
117 let addr = self.lookup_index(index)?.ok_or(())?;
118 Ok((addr, bytes_read))
119 }
120 }
121}
122
123fn address_to_hash(addr: Address) -> B256 {
124 let mut bytes = [0u8; 32];
125 bytes[12..32].copy_from_slice(addr.as_slice());
126 B256::from(bytes)
127}
128
129fn uint_to_hash(val: u64) -> B256 {
130 B256::from(U256::from(val))
131}