Skip to content

Commit 870389c

Browse files
dharmvr1mattsse
andauthored
refactor: EmptyBodyStorage block reader logic (#18508)
Co-authored-by: Matthias Seitz <[email protected]>
1 parent d357d2a commit 870389c

File tree

7 files changed

+107
-170
lines changed

7 files changed

+107
-170
lines changed

Cargo.lock

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/optimism/storage/Cargo.toml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@ workspace = true
1212

1313
[dependencies]
1414
# reth
15-
reth-node-api.workspace = true
16-
reth-chainspec.workspace = true
17-
reth-primitives-traits.workspace = true
1815
reth-optimism-primitives = { workspace = true, features = ["serde", "reth-codec"] }
1916
reth-storage-api = { workspace = true, features = ["db-api"] }
20-
reth-db-api.workspace = true
21-
reth-provider.workspace = true
2217

2318
# ethereum
24-
alloy-primitives.workspace = true
2519
alloy-consensus.workspace = true
2620

2721
[dev-dependencies]
@@ -33,11 +27,8 @@ reth-stages-types.workspace = true
3327
default = ["std"]
3428
std = [
3529
"reth-storage-api/std",
36-
"alloy-primitives/std",
3730
"reth-prune-types/std",
3831
"reth-stages-types/std",
3932
"alloy-consensus/std",
40-
"reth-chainspec/std",
4133
"reth-optimism-primitives/std",
42-
"reth-primitives-traits/std",
4334
]
Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,6 @@
1-
use alloc::{vec, vec::Vec};
2-
use alloy_consensus::{BlockBody, Header};
3-
use alloy_primitives::BlockNumber;
4-
use core::marker::PhantomData;
5-
use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
6-
use reth_db_api::transaction::{DbTx, DbTxMut};
7-
use reth_node_api::{FullNodePrimitives, FullSignedTx};
1+
use alloy_consensus::Header;
82
use reth_optimism_primitives::OpTransactionSigned;
9-
use reth_primitives_traits::{Block, FullBlockHeader, SignedTransaction};
10-
use reth_provider::{
11-
providers::{ChainStorage, NodeTypesForProvider},
12-
DatabaseProvider,
13-
};
14-
use reth_storage_api::{
15-
errors::ProviderResult, BlockBodyReader, BlockBodyWriter, ChainStorageReader,
16-
ChainStorageWriter, DBProvider, ReadBodyInput, StorageLocation,
17-
};
3+
use reth_storage_api::EmptyBodyStorage;
184

195
/// Optimism storage implementation.
20-
#[derive(Debug, Clone, Copy)]
21-
pub struct OpStorage<T = OpTransactionSigned, H = Header>(PhantomData<(T, H)>);
22-
23-
impl<T, H> Default for OpStorage<T, H> {
24-
fn default() -> Self {
25-
Self(Default::default())
26-
}
27-
}
28-
29-
impl<N, T, H> ChainStorage<N> for OpStorage<T, H>
30-
where
31-
T: FullSignedTx,
32-
H: FullBlockHeader,
33-
N: FullNodePrimitives<
34-
Block = alloy_consensus::Block<T, H>,
35-
BlockHeader = H,
36-
BlockBody = alloy_consensus::BlockBody<T, H>,
37-
SignedTx = T,
38-
>,
39-
{
40-
fn reader<TX, Types>(&self) -> impl ChainStorageReader<DatabaseProvider<TX, Types>, N>
41-
where
42-
TX: DbTx + 'static,
43-
Types: NodeTypesForProvider<Primitives = N>,
44-
{
45-
self
46-
}
47-
48-
fn writer<TX, Types>(&self) -> impl ChainStorageWriter<DatabaseProvider<TX, Types>, N>
49-
where
50-
TX: DbTxMut + DbTx + 'static,
51-
Types: NodeTypesForProvider<Primitives = N>,
52-
{
53-
self
54-
}
55-
}
56-
57-
impl<Provider, T, H> BlockBodyWriter<Provider, alloy_consensus::BlockBody<T, H>> for OpStorage<T, H>
58-
where
59-
Provider: DBProvider<Tx: DbTxMut>,
60-
T: SignedTransaction,
61-
H: FullBlockHeader,
62-
{
63-
fn write_block_bodies(
64-
&self,
65-
_provider: &Provider,
66-
_bodies: Vec<(u64, Option<alloy_consensus::BlockBody<T, H>>)>,
67-
_write_to: StorageLocation,
68-
) -> ProviderResult<()> {
69-
// noop
70-
Ok(())
71-
}
72-
73-
fn remove_block_bodies_above(
74-
&self,
75-
_provider: &Provider,
76-
_block: BlockNumber,
77-
_remove_from: StorageLocation,
78-
) -> ProviderResult<()> {
79-
// noop
80-
Ok(())
81-
}
82-
}
83-
84-
impl<Provider, T, H> BlockBodyReader<Provider> for OpStorage<T, H>
85-
where
86-
Provider: ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks> + DBProvider,
87-
T: SignedTransaction,
88-
H: FullBlockHeader,
89-
{
90-
type Block = alloy_consensus::Block<T, H>;
91-
92-
fn read_block_bodies(
93-
&self,
94-
provider: &Provider,
95-
inputs: Vec<ReadBodyInput<'_, Self::Block>>,
96-
) -> ProviderResult<Vec<<Self::Block as Block>::Body>> {
97-
let chain_spec = provider.chain_spec();
98-
99-
Ok(inputs
100-
.into_iter()
101-
.map(|(header, transactions)| BlockBody {
102-
transactions,
103-
ommers: vec![],
104-
// after shanghai the body should have an empty withdrawals list
105-
withdrawals: chain_spec
106-
.is_shanghai_active_at_timestamp(header.timestamp())
107-
.then(Default::default),
108-
})
109-
.collect())
110-
}
111-
}
6+
pub type OpStorage<T = OpTransactionSigned, H = Header> = EmptyBodyStorage<T, H>;

crates/optimism/storage/src/lib.rs

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,67 +9,26 @@
99
#![cfg_attr(not(feature = "std"), no_std)]
1010
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
1111

12-
extern crate alloc;
13-
1412
mod chain;
1513
pub use chain::OpStorage;
1614

1715
#[cfg(test)]
1816
mod tests {
1917
use reth_codecs::{test_utils::UnusedBits, validate_bitflag_backwards_compat};
20-
use reth_db_api::models::{
21-
CompactClientVersion, CompactU256, CompactU64, StoredBlockBodyIndices,
22-
StoredBlockWithdrawals,
23-
};
24-
use reth_primitives_traits::Account;
18+
2519
use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
26-
use reth_stages_types::{
27-
AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint,
28-
HeadersCheckpoint, IndexHistoryCheckpoint, StageCheckpoint, StageUnitCheckpoint,
29-
StorageHashingCheckpoint,
30-
};
3120

3221
#[test]
3322
fn test_ensure_backwards_compatibility() {
34-
assert_eq!(Account::bitflag_encoded_bytes(), 2);
35-
assert_eq!(AccountHashingCheckpoint::bitflag_encoded_bytes(), 1);
36-
assert_eq!(CheckpointBlockRange::bitflag_encoded_bytes(), 1);
37-
assert_eq!(CompactClientVersion::bitflag_encoded_bytes(), 0);
38-
assert_eq!(CompactU256::bitflag_encoded_bytes(), 1);
39-
assert_eq!(CompactU64::bitflag_encoded_bytes(), 1);
40-
assert_eq!(EntitiesCheckpoint::bitflag_encoded_bytes(), 1);
41-
assert_eq!(ExecutionCheckpoint::bitflag_encoded_bytes(), 0);
42-
assert_eq!(HeadersCheckpoint::bitflag_encoded_bytes(), 0);
43-
assert_eq!(IndexHistoryCheckpoint::bitflag_encoded_bytes(), 0);
44-
assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1);
4523
assert_eq!(PruneMode::bitflag_encoded_bytes(), 1);
4624
assert_eq!(PruneSegment::bitflag_encoded_bytes(), 1);
47-
assert_eq!(StageCheckpoint::bitflag_encoded_bytes(), 1);
48-
assert_eq!(StageUnitCheckpoint::bitflag_encoded_bytes(), 1);
49-
assert_eq!(StoredBlockBodyIndices::bitflag_encoded_bytes(), 1);
50-
assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
51-
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
5225

5326
// In case of failure, refer to the documentation of the
5427
// [`validate_bitflag_backwards_compat`] macro for detailed instructions on handling
5528
// it.
56-
validate_bitflag_backwards_compat!(Account, UnusedBits::NotZero);
57-
validate_bitflag_backwards_compat!(AccountHashingCheckpoint, UnusedBits::NotZero);
58-
validate_bitflag_backwards_compat!(CheckpointBlockRange, UnusedBits::Zero);
59-
validate_bitflag_backwards_compat!(CompactClientVersion, UnusedBits::Zero);
60-
validate_bitflag_backwards_compat!(CompactU256, UnusedBits::NotZero);
61-
validate_bitflag_backwards_compat!(CompactU64, UnusedBits::NotZero);
62-
validate_bitflag_backwards_compat!(EntitiesCheckpoint, UnusedBits::Zero);
63-
validate_bitflag_backwards_compat!(ExecutionCheckpoint, UnusedBits::Zero);
64-
validate_bitflag_backwards_compat!(HeadersCheckpoint, UnusedBits::Zero);
65-
validate_bitflag_backwards_compat!(IndexHistoryCheckpoint, UnusedBits::Zero);
29+
6630
validate_bitflag_backwards_compat!(PruneCheckpoint, UnusedBits::NotZero);
6731
validate_bitflag_backwards_compat!(PruneMode, UnusedBits::Zero);
6832
validate_bitflag_backwards_compat!(PruneSegment, UnusedBits::Zero);
69-
validate_bitflag_backwards_compat!(StageCheckpoint, UnusedBits::NotZero);
70-
validate_bitflag_backwards_compat!(StageUnitCheckpoint, UnusedBits::Zero);
71-
validate_bitflag_backwards_compat!(StoredBlockBodyIndices, UnusedBits::Zero);
72-
validate_bitflag_backwards_compat!(StoredBlockWithdrawals, UnusedBits::Zero);
73-
validate_bitflag_backwards_compat!(StorageHashingCheckpoint, UnusedBits::NotZero);
7433
}
7534
}

crates/storage/provider/src/providers/database/chain.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use reth_db_api::transaction::{DbTx, DbTxMut};
33
use reth_node_types::FullNodePrimitives;
44

55
use reth_primitives_traits::{FullBlockHeader, FullSignedTx};
6-
use reth_storage_api::{ChainStorageReader, ChainStorageWriter, EthStorage};
6+
use reth_storage_api::{ChainStorageReader, ChainStorageWriter, EmptyBodyStorage, EthStorage};
77

88
/// Trait that provides access to implementations of [`ChainStorage`]
99
pub trait ChainStorage<Primitives: FullNodePrimitives>: Send + Sync {
@@ -47,3 +47,31 @@ where
4747
self
4848
}
4949
}
50+
51+
impl<N, T, H> ChainStorage<N> for EmptyBodyStorage<T, H>
52+
where
53+
T: FullSignedTx,
54+
H: FullBlockHeader,
55+
N: FullNodePrimitives<
56+
Block = alloy_consensus::Block<T, H>,
57+
BlockHeader = H,
58+
BlockBody = alloy_consensus::BlockBody<T, H>,
59+
SignedTx = T,
60+
>,
61+
{
62+
fn reader<TX, Types>(&self) -> impl ChainStorageReader<DatabaseProvider<TX, Types>, N>
63+
where
64+
TX: DbTx + 'static,
65+
Types: NodeTypesForProvider<Primitives = N>,
66+
{
67+
self
68+
}
69+
70+
fn writer<TX, Types>(&self) -> impl ChainStorageWriter<DatabaseProvider<TX, Types>, N>
71+
where
72+
TX: DbTxMut + DbTx + 'static,
73+
Types: NodeTypesForProvider<Primitives = N>,
74+
{
75+
self
76+
}
77+
}

crates/storage/storage-api/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,13 @@ serde = [
6565
"reth-stages-types/serde",
6666
"reth-trie-common/serde",
6767
"revm-database/serde",
68-
"reth-ethereum-primitives/serde",
6968
"alloy-eips/serde",
7069
"alloy-primitives/serde",
7170
"alloy-consensus/serde",
7271
"alloy-rpc-types-engine/serde",
7372
]
7473

7574
serde-bincode-compat = [
76-
"reth-ethereum-primitives/serde-bincode-compat",
7775
"reth-execution-types/serde-bincode-compat",
7876
"reth-primitives-traits/serde-bincode-compat",
7977
"reth-trie-common/serde-bincode-compat",

crates/storage/storage-api/src/chain.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use alloc::vec::Vec;
33
use alloy_consensus::Header;
44
use alloy_primitives::BlockNumber;
55
use core::marker::PhantomData;
6-
use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
6+
use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
77
use reth_db_api::{
88
cursor::{DbCursorRO, DbCursorRW},
99
models::StoredBlockOmmers,
@@ -193,3 +193,75 @@ where
193193
Ok(bodies)
194194
}
195195
}
196+
197+
/// A noop storage for chains that don’t have custom body storage.
198+
///
199+
/// This will never read nor write additional body content such as withdrawals or ommers.
200+
/// But will respect the optionality of withdrawals if activated and fill them if the corresponding
201+
/// hardfork is activated.
202+
#[derive(Debug, Clone, Copy)]
203+
pub struct EmptyBodyStorage<T, H>(PhantomData<(T, H)>);
204+
205+
impl<T, H> Default for EmptyBodyStorage<T, H> {
206+
fn default() -> Self {
207+
Self(PhantomData)
208+
}
209+
}
210+
211+
impl<Provider, T, H> BlockBodyWriter<Provider, alloy_consensus::BlockBody<T, H>>
212+
for EmptyBodyStorage<T, H>
213+
where
214+
Provider: DBProvider<Tx: DbTxMut>,
215+
T: SignedTransaction,
216+
H: FullBlockHeader,
217+
{
218+
fn write_block_bodies(
219+
&self,
220+
_provider: &Provider,
221+
_bodies: Vec<(u64, Option<alloy_consensus::BlockBody<T, H>>)>,
222+
_write_to: StorageLocation,
223+
) -> ProviderResult<()> {
224+
// noop
225+
Ok(())
226+
}
227+
228+
fn remove_block_bodies_above(
229+
&self,
230+
_provider: &Provider,
231+
_block: BlockNumber,
232+
_remove_from: StorageLocation,
233+
) -> ProviderResult<()> {
234+
// noop
235+
Ok(())
236+
}
237+
}
238+
239+
impl<Provider, T, H> BlockBodyReader<Provider> for EmptyBodyStorage<T, H>
240+
where
241+
Provider: ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks> + DBProvider,
242+
T: SignedTransaction,
243+
H: FullBlockHeader,
244+
{
245+
type Block = alloy_consensus::Block<T, H>;
246+
247+
fn read_block_bodies(
248+
&self,
249+
provider: &Provider,
250+
inputs: Vec<ReadBodyInput<'_, Self::Block>>,
251+
) -> ProviderResult<Vec<<Self::Block as Block>::Body>> {
252+
let chain_spec = provider.chain_spec();
253+
254+
Ok(inputs
255+
.into_iter()
256+
.map(|(header, transactions)| {
257+
alloy_consensus::BlockBody {
258+
transactions,
259+
ommers: vec![], // Empty storage never has ommers
260+
withdrawals: chain_spec
261+
.is_shanghai_active_at_timestamp(header.timestamp())
262+
.then(Default::default),
263+
}
264+
})
265+
.collect())
266+
}
267+
}

0 commit comments

Comments
 (0)