Repository: paradigmxyz/reth (language: rust)

Issue:
Add dedicated Optimism Storage impl
### Describe the feature

the `EthStorage` is responsible

https://github.com/paradigmxyz/reth/blob/ea680785bec14dfeda51eb307095108fd181bd0e/crates/storage/storage-api/src/chain.rs#L89-L89

for reading and writing body data that is not transactions:

https://github.com/paradigmxyz/reth/blob/ea680785bec14dfeda51eb307095108fd181bd0e/crates/storage/storage-api/src/chain.rs#L23-L24

for optimism this is always a noop, because there are no withdrawals and ommers blocks in the body.

so we can specialize these impls for an OpStorage type:


https://github.com/paradigmxyz/reth/blob/ea680785bec14dfeda51eb307095108fd181bd0e/crates/storage/storage-api/src/chain.rs#L97-L99

https://github.com/paradigmxyz/reth/blob/ea680785bec14dfeda51eb307095108fd181bd0e/crates/storage/storage-api/src/chain.rs#L147-L147

## TODO
* introduce `OptStorage` type in reth-optimism-storage crate
* impl the traits and make all of the read/write impls noops, however we need to keep this for withdrawals: https://github.com/paradigmxyz/reth/blob/ea680785bec14dfeda51eb307095108fd181bd0e/crates/storage/storage-api/src/chain.rs#L169-L171


### Additional context

_No response_


Discussion / hints:
Can I work on this?
Hey i'm agnik, im a beginner rust dev and i realllllllly want to start working on Reth, i think i can provide a feasible solution for this issues
A possible approach would be to implement the EthStorage trait for the new OptStorage type, but have most methods return empty results or do nothing, while preserving just the withdrawal-related functionality mentioned in the final link.

Fix patch:
diff --git a/.github/assets/check_wasm.sh b/.github/assets/check_wasm.sh
index b0d7df406416..52b6570d4376 100755
--- a/.github/assets/check_wasm.sh
+++ b/.github/assets/check_wasm.sh
@@ -43,6 +43,7 @@ exclude_crates=(
   reth-optimism-node
   reth-optimism-payload-builder
   reth-optimism-rpc
+  reth-optimism-storage
   reth-optimism-chain-registry
   reth-rpc
   reth-rpc-api
diff --git a/Cargo.lock b/Cargo.lock
index 6325e1fca1b7..0ee84d949af1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8817,10 +8817,15 @@ dependencies = [
 name = "reth-optimism-storage"
 version = "1.2.0"
 dependencies = [
+ "alloy-consensus",
+ "alloy-eips",
  "alloy-primitives",
+ "reth-chainspec",
  "reth-codecs",
  "reth-db-api",
- "reth-primitives",
+ "reth-optimism-forks",
+ "reth-optimism-primitives",
+ "reth-primitives-traits",
  "reth-prune-types",
  "reth-stages-types",
  "reth-storage-api",
diff --git a/crates/optimism/storage/Cargo.toml b/crates/optimism/storage/Cargo.toml
index 3c9fde1d5160..f4494cf6e6fa 100644
--- a/crates/optimism/storage/Cargo.toml
+++ b/crates/optimism/storage/Cargo.toml
@@ -12,16 +12,22 @@ workspace = true
 
 [dependencies]
 # reth
-reth-primitives.workspace = true
+reth-chainspec.workspace = true
+reth-primitives-traits.workspace = true
+reth-optimism-forks.workspace = true
+#
+reth-optimism-primitives = { workspace = true, features = ["serde", "reth-codec"] }
 reth-trie-common.workspace = true
 reth-storage-api.workspace = true
 
 # ethereum
+alloy-eips.workspace = true
 alloy-primitives.workspace = true
+alloy-consensus.workspace = true
 revm.workspace = true
 
 [dev-dependencies]
-reth-codecs.workspace = true
+reth-codecs = { workspace = true, features = ["test-utils"] }
 reth-db-api.workspace = true
 reth-prune-types.workspace = true
 reth-stages-types.workspace = true
@@ -29,11 +35,16 @@ reth-stages-types.workspace = true
 [features]
 default = ["std"]
 std = [
-    "reth-primitives/std",
     "reth-trie-common/std",
     "reth-storage-api/std",
     "alloy-primitives/std",
     "revm/std",
     "reth-prune-types/std",
     "reth-stages-types/std",
+    "alloy-consensus/std",
+    "reth-chainspec/std",
+    "reth-optimism-forks/std",
+    "reth-optimism-primitives/std",
+    "reth-primitives-traits/std",
+    "alloy-eips/std",
 ]
diff --git a/crates/optimism/storage/src/chain.rs b/crates/optimism/storage/src/chain.rs
new file mode 100644
index 000000000000..5df84eeae466
--- /dev/null
+++ b/crates/optimism/storage/src/chain.rs
@@ -0,0 +1,78 @@
+use alloc::{vec, vec::Vec};
+use alloy_consensus::Header;
+use alloy_primitives::BlockNumber;
+use core::marker::PhantomData;
+use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
+use reth_optimism_forks::OpHardforks;
+use reth_optimism_primitives::OpTransactionSigned;
+use reth_primitives_traits::{Block, FullBlockHeader, SignedTransaction};
+use reth_storage_api::{
+    errors::ProviderResult, BlockBodyReader, BlockBodyWriter, DBProvider, ReadBodyInput,
+    StorageLocation,
+};
+
+/// Optimism storage implementation.
+#[derive(Debug, Clone, Copy)]
+pub struct OptStorage<T = OpTransactionSigned, H = Header>(PhantomData<(T, H)>);
+
+impl<Provider, T, H> BlockBodyWriter<Provider, alloy_consensus::BlockBody<T, H>>
+    for OptStorage<T, H>
+where
+    T: SignedTransaction,
+    H: FullBlockHeader,
+{
+    fn write_block_bodies(
+        &self,
+        _provider: &Provider,
+        _bodies: Vec<(u64, Option<alloy_consensus::BlockBody<T, H>>)>,
+        _write_to: StorageLocation,
+    ) -> ProviderResult<()> {
+        // noop
+        Ok(())
+    }
+
+    fn remove_block_bodies_above(
+        &self,
+        _provider: &Provider,
+        _block: BlockNumber,
+        _remove_from: StorageLocation,
+    ) -> ProviderResult<()> {
+        // noop
+        Ok(())
+    }
+}
+
+impl<Provider, T, H> BlockBodyReader<Provider> for OptStorage<T, H>
+where
+    Provider: ChainSpecProvider<ChainSpec: EthChainSpec + OpHardforks> + DBProvider,
+    T: SignedTransaction,
+    H: FullBlockHeader,
+{
+    type Block = alloy_consensus::Block<T, H>;
+
+    fn read_block_bodies(
+        &self,
+        provider: &Provider,
+        inputs: Vec<ReadBodyInput<'_, Self::Block>>,
+    ) -> ProviderResult<Vec<<Self::Block as Block>::Body>> {
+        let chain_spec = provider.chain_spec();
+
+        let mut bodies = Vec::with_capacity(inputs.len());
+
+        for (header, transactions) in inputs {
+            let mut withdrawals = None;
+            if chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) {
+                // after shanghai the body should have an empty withdrawals list
+                withdrawals.replace(vec![].into());
+            }
+
+            bodies.push(alloy_consensus::BlockBody::<T, H> {
+                transactions,
+                ommers: vec![],
+                withdrawals,
+            });
+        }
+
+        Ok(bodies)
+    }
+}
diff --git a/crates/optimism/storage/src/lib.rs b/crates/optimism/storage/src/lib.rs
index ef088f7134b1..d26140ace47c 100644
--- a/crates/optimism/storage/src/lib.rs
+++ b/crates/optimism/storage/src/lib.rs
@@ -8,6 +8,11 @@
 #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
 #![cfg_attr(not(feature = "std"), no_std)]
 
+extern crate alloc;
+
+mod chain;
+pub use chain::OptStorage;
+
 pub mod predeploys;
 pub use predeploys::{withdrawals_root, withdrawals_root_prehashed};
 
@@ -18,7 +23,7 @@ mod tests {
         CompactClientVersion, CompactU256, CompactU64, StoredBlockBodyIndices,
         StoredBlockWithdrawals,
     };
-    use reth_primitives::Account;
+    use reth_primitives_traits::Account;
     use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
     use reth_stages_types::{
         AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint,


Test patch: