Skip to content

Commit 0d0ecd3

Browse files
authored
feat: perf improvements for build_pending_state (#184)
* wip: limit max depth of pending state * track pending snapshot height accurately * clean up unused imports * move PendingBlocksAPI impl to pending_blocks.rs * rustfmt * update err msg
1 parent 54bb000 commit 0d0ecd3

File tree

17 files changed

+289
-213
lines changed

17 files changed

+289
-213
lines changed

crates/flashblocks-rpc/src/pending_blocks.rs

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1+
use std::sync::Arc;
2+
13
use alloy_consensus::{Header, Sealed};
24
use alloy_eips::BlockNumberOrTag;
35
use alloy_primitives::{
6+
Address, B256, BlockNumber, TxHash, U256,
47
map::foldhash::{HashMap, HashMapExt},
5-
Address, BlockNumber, TxHash, B256, U256,
68
};
79
use alloy_provider::network::TransactionResponse;
8-
use alloy_rpc_types::{state::StateOverride, BlockTransactions};
10+
use alloy_rpc_types::{BlockTransactions, state::StateOverride};
911
use alloy_rpc_types_eth::{Filter, Header as RPCHeader, Log};
12+
use arc_swap::Guard;
1013
use eyre::eyre;
1114
use op_alloy_network::Optimism;
1215
use op_alloy_rpc_types::{OpTransactionReceipt, Transaction};
1316
use reth::revm::{db::Cache, state::EvmState};
14-
use reth_rpc_eth_api::RpcBlock;
17+
use reth_rpc_convert::RpcTransaction;
18+
use reth_rpc_eth_api::{RpcBlock, RpcReceipt};
1519

16-
use crate::subscription::Flashblock;
20+
use crate::{rpc::PendingBlocksAPI, subscription::Flashblock};
1721

1822
pub struct PendingBlocksBuilder {
1923
flashblocks: Vec<Flashblock>,
@@ -25,6 +29,7 @@ pub struct PendingBlocksBuilder {
2529
transaction_receipts: HashMap<B256, OpTransactionReceipt>,
2630
transactions_by_hash: HashMap<B256, Transaction>,
2731
transaction_state: HashMap<B256, EvmState>,
32+
transaction_senders: HashMap<B256, Address>,
2833
state_overrides: Option<StateOverride>,
2934

3035
db_cache: Cache,
@@ -41,6 +46,7 @@ impl PendingBlocksBuilder {
4146
transaction_receipts: HashMap::new(),
4247
transactions_by_hash: HashMap::new(),
4348
transaction_state: HashMap::new(),
49+
transaction_senders: HashMap::new(),
4450
state_overrides: None,
4551
db_cache: Cache::default(),
4652
}
@@ -77,6 +83,12 @@ impl PendingBlocksBuilder {
7783
self
7884
}
7985

86+
#[inline]
87+
pub(crate) fn with_transaction_sender(&mut self, hash: B256, sender: Address) -> &Self {
88+
self.transaction_senders.insert(hash, sender);
89+
self
90+
}
91+
8092
#[inline]
8193
pub(crate) fn increment_nonce(&mut self, sender: Address) -> &Self {
8294
let zero = U256::from(0);
@@ -122,6 +134,7 @@ impl PendingBlocksBuilder {
122134
transaction_receipts: self.transaction_receipts,
123135
transactions_by_hash: self.transactions_by_hash,
124136
transaction_state: self.transaction_state,
137+
transaction_senders: self.transaction_senders,
125138
state_overrides: self.state_overrides,
126139
db_cache: self.db_cache,
127140
})
@@ -139,6 +152,7 @@ pub struct PendingBlocks {
139152
transaction_receipts: HashMap<B256, OpTransactionReceipt>,
140153
transactions_by_hash: HashMap<B256, Transaction>,
141154
transaction_state: HashMap<B256, EvmState>,
155+
transaction_senders: HashMap<B256, Address>,
142156
state_overrides: Option<StateOverride>,
143157

144158
db_cache: Cache,
@@ -153,6 +167,10 @@ impl PendingBlocks {
153167
BlockNumberOrTag::Number(self.headers.first().unwrap().number - 1)
154168
}
155169

170+
pub fn earliest_block_number(&self) -> BlockNumber {
171+
self.headers.first().unwrap().number
172+
}
173+
156174
pub fn latest_flashblock_index(&self) -> u64 {
157175
self.flashblocks.last().unwrap().index
158176
}
@@ -165,8 +183,12 @@ impl PendingBlocks {
165183
self.flashblocks.clone()
166184
}
167185

168-
pub fn get_transaction_state(&self, hash: B256) -> Option<EvmState> {
169-
self.transaction_state.get(&hash).cloned()
186+
pub fn get_transaction_state(&self, hash: &B256) -> Option<EvmState> {
187+
self.transaction_state.get(hash).cloned()
188+
}
189+
190+
pub fn get_transaction_sender(&self, tx_hash: &B256) -> Option<Address> {
191+
self.transaction_senders.get(tx_hash).cloned()
170192
}
171193

172194
pub fn get_db_cache(&self) -> Cache {
@@ -236,3 +258,43 @@ impl PendingBlocks {
236258
logs
237259
}
238260
}
261+
262+
impl PendingBlocksAPI for Guard<Option<Arc<PendingBlocks>>> {
263+
fn get_canonical_block_number(&self) -> BlockNumberOrTag {
264+
self.as_ref().map(|pb| pb.canonical_block_number()).unwrap_or(BlockNumberOrTag::Latest)
265+
}
266+
267+
fn get_transaction_count(&self, address: Address) -> U256 {
268+
self.as_ref().map(|pb| pb.get_transaction_count(address)).unwrap_or_else(|| U256::from(0))
269+
}
270+
271+
fn get_block(&self, full: bool) -> Option<RpcBlock<Optimism>> {
272+
self.as_ref().map(|pb| pb.get_latest_block(full))
273+
}
274+
275+
fn get_transaction_receipt(
276+
&self,
277+
tx_hash: alloy_primitives::TxHash,
278+
) -> Option<RpcReceipt<Optimism>> {
279+
self.as_ref().and_then(|pb| pb.get_receipt(tx_hash))
280+
}
281+
282+
fn get_transaction_by_hash(
283+
&self,
284+
tx_hash: alloy_primitives::TxHash,
285+
) -> Option<RpcTransaction<Optimism>> {
286+
self.as_ref().and_then(|pb| pb.get_transaction_by_hash(tx_hash))
287+
}
288+
289+
fn get_balance(&self, address: Address) -> Option<U256> {
290+
self.as_ref().and_then(|pb| pb.get_balance(address))
291+
}
292+
293+
fn get_state_overrides(&self) -> Option<StateOverride> {
294+
self.as_ref().map(|pb| pb.get_state_overrides()).unwrap_or_default()
295+
}
296+
297+
fn get_pending_logs(&self, filter: &Filter) -> Vec<Log> {
298+
self.as_ref().map(|pb| pb.get_pending_logs(filter)).unwrap_or_default()
299+
}
300+
}

crates/flashblocks-rpc/src/rpc.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,36 @@ use std::{sync::Arc, time::Duration};
22

33
use alloy_eips::{BlockId, BlockNumberOrTag};
44
use alloy_primitives::{
5-
map::foldhash::{HashSet, HashSetExt},
65
Address, TxHash, U256,
6+
map::foldhash::{HashSet, HashSetExt},
77
};
88
use alloy_rpc_types::{
9+
BlockOverrides,
910
simulate::{SimBlock, SimulatePayload, SimulatedBlock},
1011
state::{EvmOverrides, StateOverride, StateOverridesBuilder},
11-
BlockOverrides,
1212
};
1313
use alloy_rpc_types_eth::{Filter, Log};
1414
use arc_swap::Guard;
1515
use jsonrpsee::{
16-
core::{async_trait, RpcResult},
16+
core::{RpcResult, async_trait},
1717
proc_macros::rpc,
1818
};
19-
use jsonrpsee_types::{error::INVALID_PARAMS_CODE, ErrorObjectOwned};
19+
use jsonrpsee_types::{ErrorObjectOwned, error::INVALID_PARAMS_CODE};
2020
use op_alloy_network::Optimism;
2121
use op_alloy_rpc_types::OpTransactionRequest;
2222
use reth::{
2323
providers::CanonStateSubscriptions,
2424
rpc::{eth::EthFilter, server_types::eth::EthApiError},
2525
};
2626
use reth_rpc_eth_api::{
27-
helpers::{EthBlocks, EthCall, EthState, EthTransactions, FullEthApi},
2827
EthApiTypes, EthFilterApiServer, RpcBlock, RpcReceipt, RpcTransaction,
28+
helpers::{EthBlocks, EthCall, EthState, EthTransactions, FullEthApi},
2929
};
3030
use tokio::{
3131
sync::{broadcast, broadcast::error::RecvError},
3232
time,
3333
};
34-
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
34+
use tokio_stream::{StreamExt, wrappers::BroadcastStream};
3535
use tracing::{debug, trace, warn};
3636

3737
use crate::{metrics::Metrics, pending_blocks::PendingBlocks};
@@ -91,7 +91,7 @@ pub trait EthApiOverride {
9191

9292
#[method(name = "getBalance")]
9393
async fn get_balance(&self, address: Address, block_number: Option<BlockId>)
94-
-> RpcResult<U256>;
94+
-> RpcResult<U256>;
9595

9696
#[method(name = "getTransactionCount")]
9797
async fn get_transaction_count(

0 commit comments

Comments
 (0)