arbos/blockhash/
mod.rs

1use alloy_primitives::{keccak256, B256};
2use revm::Database;
3
4use arb_storage::{Storage, StorageBackedUint64};
5
6pub struct Blockhashes<D> {
7    backing_storage: Storage<D>,
8    l1_block_number: StorageBackedUint64<D>,
9}
10
11pub fn initialize_blockhashes<D: Database>(_backing_storage: &Storage<D>) {
12    // no-op: next_block_number is already zero
13}
14
15pub fn open_blockhashes<D: Database>(backing_storage: Storage<D>) -> Blockhashes<D> {
16    let l1_block_number =
17        StorageBackedUint64::new(backing_storage.state_ptr(), backing_storage.base_key(), 0);
18    Blockhashes {
19        backing_storage,
20        l1_block_number,
21    }
22}
23
24impl<D: Database> Blockhashes<D> {
25    pub fn l1_block_number(&self) -> Result<u64, ()> {
26        self.l1_block_number.get()
27    }
28
29    pub fn block_hash(&self, number: u64) -> Result<Option<B256>, ()> {
30        let current_number = self.l1_block_number.get()?;
31        if number >= current_number || number + 256 < current_number {
32            return Ok(None);
33        }
34        let hash = self.backing_storage.get_by_uint64(1 + (number % 256))?;
35        Ok(Some(hash))
36    }
37
38    pub fn record_new_l1_block(
39        &self,
40        number: u64,
41        block_hash: B256,
42        arbos_version: u64,
43    ) -> Result<(), ()> {
44        let mut next_number = self.l1_block_number.get()?;
45
46        if number < next_number {
47            return Ok(());
48        }
49
50        if next_number + 256 < number {
51            next_number = number - 256;
52        }
53
54        while next_number + 1 < number {
55            next_number += 1;
56
57            let mut next_num_buf = [0u8; 8];
58            if arbos_version >= 8 {
59                next_num_buf.copy_from_slice(&next_number.to_le_bytes());
60            }
61
62            let mut combined = Vec::with_capacity(40);
63            combined.extend_from_slice(block_hash.as_slice());
64            combined.extend_from_slice(&next_num_buf);
65            let fill = keccak256(&combined);
66
67            self.backing_storage
68                .set_by_uint64(1 + (next_number % 256), fill)?;
69        }
70
71        self.backing_storage
72            .set_by_uint64(1 + (number % 256), block_hash)?;
73        self.l1_block_number.set(number + 1)
74    }
75}