Skip to content

Commit 294a28e

Browse files
committed
refactor: simplify meter_block API by accepting provider directly
Instead of requiring the caller to pass a state provider and parent header separately, meter_block now accepts a provider that implements both StateProviderFactory and HeaderProvider. This allows the function to fetch the parent header and state internally, resulting in a cleaner API.
1 parent 6e5d444 commit 294a28e

File tree

3 files changed

+46
-87
lines changed

3 files changed

+46
-87
lines changed

crates/rpc/src/base/block.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
use std::{sync::Arc, time::Instant};
22

3-
use alloy_consensus::{BlockHeader, transaction::SignerRecoverable};
3+
use alloy_consensus::{BlockHeader, Header, transaction::SignerRecoverable};
44
use alloy_primitives::B256;
55
use eyre::{Result as EyreResult, eyre};
66
use reth::revm::db::State;
77
use reth_evm::{ConfigureEvm, execute::BlockBuilder};
88
use reth_optimism_chainspec::OpChainSpec;
99
use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes};
1010
use reth_optimism_primitives::OpBlock;
11-
use reth_primitives_traits::{Block as BlockT, SealedHeader};
12-
use reth_provider::{HashedPostStateProvider, StateRootProvider};
11+
use reth_primitives_traits::Block as BlockT;
12+
use reth_provider::{HeaderProvider, StateProviderFactory};
1313

1414
use super::types::{MeterBlockResponse, MeterBlockTransactions};
1515

1616
/// Re-executes a block and meters execution time, state root calculation time, and total time.
1717
///
18-
/// Takes a state provider at the parent block, the chain spec, and the block to meter.
18+
/// Takes a provider, the chain spec, and the block to meter.
1919
///
2020
/// Returns `MeterBlockResponse` containing:
2121
/// - Block hash
@@ -32,20 +32,28 @@ use super::types::{MeterBlockResponse, MeterBlockTransactions};
3232
/// State root calculation timing is most accurate for recent blocks where state tries are
3333
/// cached. For older blocks, trie nodes may not be cached, which can significantly inflate
3434
/// the `state_root_time_us` value.
35-
pub fn meter_block<SP>(
36-
state_provider: SP,
35+
pub fn meter_block<P>(
36+
provider: P,
3737
chain_spec: Arc<OpChainSpec>,
3838
block: &OpBlock,
39-
parent_header: &SealedHeader,
4039
) -> EyreResult<MeterBlockResponse>
4140
where
42-
SP: reth_provider::StateProvider + StateRootProvider + HashedPostStateProvider,
41+
P: StateProviderFactory + HeaderProvider<Header = Header>,
4342
{
4443
let block_hash = block.header().hash_slow();
4544
let block_number = block.header().number();
4645
let transactions: Vec<_> = block.body().transactions().cloned().collect();
4746
let tx_count = transactions.len();
4847

48+
// Get parent header
49+
let parent_hash = block.header().parent_hash();
50+
let parent_header = provider
51+
.sealed_header_by_hash(parent_hash)?
52+
.ok_or_else(|| eyre!("Parent header not found: {}", parent_hash))?;
53+
54+
// Get state provider at parent block
55+
let state_provider = provider.state_by_block_hash(parent_hash)?;
56+
4957
// Create state database from parent state
5058
let state_db = reth::revm::database::StateProviderDatabase::new(&state_provider);
5159
let mut db = State::builder().with_database(state_db).with_bundle_update().build();
@@ -80,7 +88,7 @@ where
8088
let evm_start = Instant::now();
8189
{
8290
let evm_config = OpEvmConfig::optimism(chain_spec);
83-
let mut builder = evm_config.builder_for_next_block(&mut db, parent_header, attributes)?;
91+
let mut builder = evm_config.builder_for_next_block(&mut db, &parent_header, attributes)?;
8492

8593
builder.apply_pre_execution_changes()?;
8694

crates/rpc/src/base/meter_rpc.rs

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use jsonrpsee::core::{RpcResult, async_trait};
55
use reth::providers::BlockReaderIdExt;
66
use reth_optimism_chainspec::OpChainSpec;
77
use reth_optimism_primitives::OpBlock;
8-
use reth_primitives_traits::Block as BlockT;
9-
use reth_provider::{BlockReader, ChainSpecProvider, StateProviderFactory};
8+
use reth_provider::{BlockReader, ChainSpecProvider, HeaderProvider, StateProviderFactory};
109
use tips_core::types::{Bundle, MeterBundleResponse, ParsedBundle};
1110
use tracing::{error, info};
1211

@@ -27,6 +26,7 @@ where
2726
+ ChainSpecProvider<ChainSpec = OpChainSpec>
2827
+ BlockReaderIdExt<Header = Header>
2928
+ BlockReader<Block = OpBlock>
29+
+ HeaderProvider<Header = Header>
3030
+ Clone,
3131
{
3232
/// Creates a new instance of MeteringApi
@@ -42,6 +42,7 @@ where
4242
+ ChainSpecProvider<ChainSpec = OpChainSpec>
4343
+ BlockReaderIdExt<Header = Header>
4444
+ BlockReader<Block = OpBlock>
45+
+ HeaderProvider<Header = Header>
4546
+ Clone
4647
+ Send
4748
+ Sync
@@ -212,58 +213,23 @@ where
212213
+ ChainSpecProvider<ChainSpec = OpChainSpec>
213214
+ BlockReaderIdExt<Header = Header>
214215
+ BlockReader<Block = OpBlock>
216+
+ HeaderProvider<Header = Header>
215217
+ Clone
216218
+ Send
217219
+ Sync
218220
+ 'static,
219221
{
220222
/// Internal helper to meter a block's execution
221223
fn meter_block_internal(&self, block: &OpBlock) -> RpcResult<MeterBlockResponse> {
222-
// Get parent header
223-
let parent_hash = block.header().parent_hash;
224-
let parent_header = self
225-
.provider
226-
.sealed_header_by_hash(parent_hash)
227-
.map_err(|e| {
228-
error!(error = %e, "Failed to get parent header");
224+
meter_block(self.provider.clone(), self.provider.chain_spec().clone(), block).map_err(
225+
|e| {
226+
error!(error = %e, "Block metering failed");
229227
jsonrpsee::types::ErrorObjectOwned::owned(
230228
jsonrpsee::types::ErrorCode::InternalError.code(),
231-
format!("Failed to get parent header: {}", e),
229+
format!("Block metering failed: {}", e),
232230
None::<()>,
233231
)
234-
})?
235-
.ok_or_else(|| {
236-
jsonrpsee::types::ErrorObjectOwned::owned(
237-
jsonrpsee::types::ErrorCode::InternalError.code(),
238-
format!("Parent block not found: {}", parent_hash),
239-
None::<()>,
240-
)
241-
})?;
242-
243-
// Get state provider at parent block
244-
let state_provider = self.provider.state_by_block_hash(parent_hash).map_err(|e| {
245-
error!(error = %e, "Failed to get state provider for parent block");
246-
jsonrpsee::types::ErrorObjectOwned::owned(
247-
jsonrpsee::types::ErrorCode::InternalError.code(),
248-
format!("Failed to get state provider: {}", e),
249-
None::<()>,
250-
)
251-
})?;
252-
253-
// Meter the block
254-
meter_block(
255-
state_provider,
256-
self.provider.chain_spec().clone(),
257-
block,
258-
&parent_header,
232+
},
259233
)
260-
.map_err(|e| {
261-
error!(error = %e, "Block metering failed");
262-
jsonrpsee::types::ErrorObjectOwned::owned(
263-
jsonrpsee::types::ErrorCode::InternalError.code(),
264-
format!("Block metering failed: {}", e),
265-
None::<()>,
266-
)
267-
})
268234
}
269235
}

crates/rpc/tests/meter_block.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use reth_db::{DatabaseEnv, test_utils::TempDatabase};
1414
use reth_optimism_chainspec::{BASE_MAINNET, OpChainSpec, OpChainSpecBuilder};
1515
use reth_optimism_node::OpNode;
1616
use reth_optimism_primitives::{OpBlock, OpBlockBody, OpTransactionSigned};
17-
use reth_primitives_traits::{Block as BlockT, SealedHeader};
18-
use reth_provider::{HeaderProvider, StateProviderFactory, providers::BlockchainProvider};
17+
use reth_primitives_traits::Block as BlockT;
18+
use reth_provider::{HeaderProvider, providers::BlockchainProvider};
1919
use reth_testing_utils::generators::generate_keys;
2020
use reth_transaction_pool::test_utils::TransactionBuilder;
2121

@@ -30,7 +30,9 @@ enum User {
3030
#[derive(Debug, Clone)]
3131
struct TestHarness {
3232
provider: BlockchainProvider<NodeTypes>,
33-
header: SealedHeader,
33+
genesis_header_hash: B256,
34+
genesis_header_number: u64,
35+
genesis_header_timestamp: u64,
3436
chain_spec: Arc<OpChainSpec>,
3537
user_to_private_key: std::collections::HashMap<User, B256>,
3638
}
@@ -83,17 +85,24 @@ fn setup_harness() -> eyre::Result<TestHarness> {
8385
.context("fetching genesis header")?
8486
.expect("genesis header exists");
8587

86-
Ok(TestHarness { provider, header, chain_spec, user_to_private_key })
88+
Ok(TestHarness {
89+
provider,
90+
genesis_header_hash: header.hash(),
91+
genesis_header_number: header.number(),
92+
genesis_header_timestamp: header.timestamp(),
93+
chain_spec,
94+
user_to_private_key,
95+
})
8796
}
8897

8998
fn create_block_with_transactions(
9099
harness: &TestHarness,
91100
transactions: Vec<OpTransactionSigned>,
92101
) -> OpBlock {
93102
let header = Header {
94-
parent_hash: harness.header.hash(),
95-
number: harness.header.number() + 1,
96-
timestamp: harness.header.timestamp() + 2,
103+
parent_hash: harness.genesis_header_hash,
104+
number: harness.genesis_header_number + 1,
105+
timestamp: harness.genesis_header_timestamp + 2,
97106
gas_limit: 30_000_000,
98107
beneficiary: Address::random(),
99108
base_fee_per_gas: Some(1),
@@ -113,13 +122,7 @@ fn meter_block_empty_transactions() -> eyre::Result<()> {
113122

114123
let block = create_block_with_transactions(&harness, vec![]);
115124

116-
let state_provider = harness
117-
.provider
118-
.state_by_block_hash(harness.header.hash())
119-
.context("getting state provider")?;
120-
121-
let response =
122-
meter_block(state_provider, harness.chain_spec.clone(), &block, &harness.header)?;
125+
let response = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block)?;
123126

124127
assert_eq!(response.block_hash, block.header().hash_slow());
125128
assert_eq!(response.block_number, block.header().number());
@@ -157,13 +160,7 @@ fn meter_block_single_transaction() -> eyre::Result<()> {
157160

158161
let block = create_block_with_transactions(&harness, vec![tx]);
159162

160-
let state_provider = harness
161-
.provider
162-
.state_by_block_hash(harness.header.hash())
163-
.context("getting state provider")?;
164-
165-
let response =
166-
meter_block(state_provider, harness.chain_spec.clone(), &block, &harness.header)?;
163+
let response = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block)?;
167164

168165
assert_eq!(response.block_hash, block.header().hash_slow());
169166
assert_eq!(response.block_number, block.header().number());
@@ -228,13 +225,7 @@ fn meter_block_multiple_transactions() -> eyre::Result<()> {
228225

229226
let block = create_block_with_transactions(&harness, vec![tx_1, tx_2]);
230227

231-
let state_provider = harness
232-
.provider
233-
.state_by_block_hash(harness.header.hash())
234-
.context("getting state provider")?;
235-
236-
let response =
237-
meter_block(state_provider, harness.chain_spec.clone(), &block, &harness.header)?;
228+
let response = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block)?;
238229

239230
assert_eq!(response.block_hash, block.header().hash_slow());
240231
assert_eq!(response.block_number, block.header().number());
@@ -292,13 +283,7 @@ fn meter_block_timing_consistency() -> eyre::Result<()> {
292283

293284
let block = create_block_with_transactions(&harness, vec![tx]);
294285

295-
let state_provider = harness
296-
.provider
297-
.state_by_block_hash(harness.header.hash())
298-
.context("getting state provider")?;
299-
300-
let response =
301-
meter_block(state_provider, harness.chain_spec.clone(), &block, &harness.header)?;
286+
let response = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block)?;
302287

303288
// Verify timing invariants
304289
assert!(response.signer_recovery_time_us > 0, "signer recovery time must be positive");

0 commit comments

Comments
 (0)