|  | 
|  | 1 | +use crate::journal::{BundleStateIndex, JournalDecode, JournalDecodeError, JournalEncode}; | 
|  | 2 | +use alloy::primitives::{keccak256, B256}; | 
|  | 3 | +use std::sync::OnceLock; | 
|  | 4 | + | 
|  | 5 | +/// Journal associated with a block | 
|  | 6 | +#[derive(Debug, Clone, PartialEq, Eq)] | 
|  | 7 | +pub struct BlockUpdate<'a> { | 
|  | 8 | +    /// The height of the block. | 
|  | 9 | +    height: u64, | 
|  | 10 | + | 
|  | 11 | +    /// The previous journal hash. | 
|  | 12 | +    prev_journal_hash: B256, | 
|  | 13 | + | 
|  | 14 | +    /// The indexed changes. | 
|  | 15 | +    journal: BundleStateIndex<'a>, | 
|  | 16 | + | 
|  | 17 | +    /// The serialized journal | 
|  | 18 | +    serialized: OnceLock<Vec<u8>>, | 
|  | 19 | + | 
|  | 20 | +    /// The hash of the serialized journal | 
|  | 21 | +    hash: OnceLock<B256>, | 
|  | 22 | +} | 
|  | 23 | + | 
|  | 24 | +impl<'a> BlockUpdate<'a> { | 
|  | 25 | +    /// Create a new block update. | 
|  | 26 | +    pub const fn new(height: u64, prev_journal_hash: B256, journal: BundleStateIndex<'a>) -> Self { | 
|  | 27 | +        Self { | 
|  | 28 | +            height, | 
|  | 29 | +            prev_journal_hash, | 
|  | 30 | +            journal, | 
|  | 31 | +            serialized: OnceLock::new(), | 
|  | 32 | +            hash: OnceLock::new(), | 
|  | 33 | +        } | 
|  | 34 | +    } | 
|  | 35 | + | 
|  | 36 | +    /// Get the height of the block. | 
|  | 37 | +    pub const fn height(&self) -> u64 { | 
|  | 38 | +        self.height | 
|  | 39 | +    } | 
|  | 40 | + | 
|  | 41 | +    /// Get the previous journal hash. | 
|  | 42 | +    pub const fn prev_journal_hash(&self) -> B256 { | 
|  | 43 | +        self.prev_journal_hash | 
|  | 44 | +    } | 
|  | 45 | + | 
|  | 46 | +    /// Get the journal index. | 
|  | 47 | +    pub const fn journal(&self) -> &BundleStateIndex<'a> { | 
|  | 48 | +        &self.journal | 
|  | 49 | +    } | 
|  | 50 | + | 
|  | 51 | +    /// Serialize the block update. | 
|  | 52 | +    pub fn serialized(&self) -> &[u8] { | 
|  | 53 | +        self.serialized.get_or_init(|| JournalEncode::encoded(self)).as_slice() | 
|  | 54 | +    } | 
|  | 55 | + | 
|  | 56 | +    /// Serialize and hash the block update. | 
|  | 57 | +    pub fn journal_hash(&self) -> B256 { | 
|  | 58 | +        *self.hash.get_or_init(|| keccak256(self.serialized())) | 
|  | 59 | +    } | 
|  | 60 | +} | 
|  | 61 | + | 
|  | 62 | +impl JournalEncode for BlockUpdate<'_> { | 
|  | 63 | +    fn serialized_size(&self) -> usize { | 
|  | 64 | +        8 + 32 + self.journal.serialized_size() | 
|  | 65 | +    } | 
|  | 66 | + | 
|  | 67 | +    fn encode(&self, buf: &mut dyn alloy::rlp::BufMut) { | 
|  | 68 | +        self.height.encode(buf); | 
|  | 69 | +        self.prev_journal_hash.encode(buf); | 
|  | 70 | +        self.journal.encode(buf); | 
|  | 71 | +    } | 
|  | 72 | +} | 
|  | 73 | + | 
|  | 74 | +impl JournalDecode for BlockUpdate<'static> { | 
|  | 75 | +    fn decode(buf: &mut &[u8]) -> Result<Self, JournalDecodeError> { | 
|  | 76 | +        let original = *buf; | 
|  | 77 | +        Ok(Self { | 
|  | 78 | +            height: JournalDecode::decode(buf)?, | 
|  | 79 | +            prev_journal_hash: JournalDecode::decode(buf)?, | 
|  | 80 | +            journal: JournalDecode::decode(buf)?, | 
|  | 81 | +            serialized: OnceLock::from(original.to_vec()), | 
|  | 82 | +            hash: OnceLock::from(keccak256(original)), | 
|  | 83 | +        }) | 
|  | 84 | +    } | 
|  | 85 | +} | 
0 commit comments