use crate::{ node::{ primitives::tx_wrapper::{convert_to_eth_block_body, convert_to_hl_block_body}, types::ReadPrecompileCalls, }, HlBlock, HlBlockBody, HlPrimitives, }; use alloy_consensus::BlockHeader; use alloy_primitives::Bytes; use reth_chainspec::EthereumHardforks; use reth_db::{ cursor::{DbCursorRO, DbCursorRW}, transaction::{DbTx, DbTxMut}, DbTxUnwindExt, }; use reth_provider::{ providers::{ChainStorage, NodeTypesForProvider}, BlockBodyReader, BlockBodyWriter, ChainSpecProvider, ChainStorageReader, ChainStorageWriter, DBProvider, DatabaseProvider, EthStorage, ProviderResult, ReadBodyInput, StorageLocation, }; pub mod tables; #[derive(Debug, Clone, Default)] #[non_exhaustive] pub struct HlStorage(EthStorage); impl HlStorage { fn write_precompile_calls( &self, provider: &Provider, inputs: Vec<(u64, Option)>, ) -> ProviderResult<()> where Provider: DBProvider, { let mut precompile_calls_cursor = provider.tx_ref().cursor_write::()?; for (block_number, read_precompile_calls) in inputs { let Some(read_precompile_calls) = read_precompile_calls else { continue; }; precompile_calls_cursor.append( block_number, &Bytes::copy_from_slice( &rmp_serde::to_vec(&read_precompile_calls) .expect("Failed to serialize read precompile calls"), ), )?; } Ok(()) } fn read_precompile_calls( &self, provider: &Provider, inputs: &[ReadBodyInput<'_, HlBlock>], ) -> ProviderResult>> where Provider: DBProvider, { let mut read_precompile_calls = Vec::with_capacity(inputs.len()); let mut precompile_calls_cursor = provider.tx_ref().cursor_read::()?; for (header, _transactions) in inputs { let precompile_calls = precompile_calls_cursor .seek_exact(header.number())? .map(|(_, calls)| calls) .map(|calls| rmp_serde::from_slice(&calls).unwrap()); read_precompile_calls.push(precompile_calls); } Ok(read_precompile_calls) } } impl BlockBodyWriter for HlStorage where Provider: DBProvider, { fn write_block_bodies( &self, provider: &Provider, bodies: Vec<(u64, Option)>, write_to: StorageLocation, ) -> ProviderResult<()> { let mut eth_bodies = Vec::with_capacity(bodies.len()); let mut read_precompile_calls = Vec::with_capacity(bodies.len()); for (block_number, body) in bodies { match body { Some(HlBlockBody { inner, sidecars: _, read_precompile_calls: rpc }) => { eth_bodies.push((block_number, Some(convert_to_eth_block_body(inner)))); read_precompile_calls.push((block_number, rpc)); } None => { eth_bodies.push((block_number, None)); read_precompile_calls.push((block_number, None)); } } } self.0.write_block_bodies(provider, eth_bodies, write_to)?; self.write_precompile_calls(provider, read_precompile_calls)?; Ok(()) } fn remove_block_bodies_above( &self, provider: &Provider, block: u64, remove_from: StorageLocation, ) -> ProviderResult<()> { self.0.remove_block_bodies_above(provider, block, remove_from)?; provider.tx_ref().unwind_table_by_num::(block)?; Ok(()) } } impl BlockBodyReader for HlStorage where Provider: DBProvider + ChainSpecProvider, { type Block = HlBlock; fn read_block_bodies( &self, provider: &Provider, inputs: Vec>, ) -> ProviderResult> { let read_precompile_calls = self.read_precompile_calls(provider, &inputs)?; let eth_bodies = self.0.read_block_bodies( provider, inputs .into_iter() .map(|(header, transactions)| { (header, transactions.into_iter().map(|tx| tx.into_inner()).collect()) }) .collect(), )?; // NOTE: sidecars are not used in HyperEVM yet. Ok(eth_bodies .into_iter() .zip(read_precompile_calls) .map(|(inner, read_precompile_calls)| HlBlockBody { inner: convert_to_hl_block_body(inner), sidecars: None, read_precompile_calls, }) .collect()) } } impl ChainStorage for HlStorage { fn reader( &self, ) -> impl ChainStorageReader, HlPrimitives> where TX: DbTx + 'static, Types: NodeTypesForProvider, { self } fn writer( &self, ) -> impl ChainStorageWriter, HlPrimitives> where TX: DbTxMut + DbTx + 'static, Types: NodeTypesForProvider, { self } }