Skip to content

Commit

Permalink
feat: make txpool rpc optional (#1104) (#1125)
Browse files Browse the repository at this point in the history
  • Loading branch information
koushiro authored Jul 31, 2023
1 parent 7d93355 commit 22277c2
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 37 deletions.
3 changes: 3 additions & 0 deletions client/rpc-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ jsonrpsee = { workspace = true, features = ["server", "macros"] }
rustc-hex = "2.1.0"
serde = { workspace = true }
serde_json = { workspace = true }

[features]
txpool = []
4 changes: 3 additions & 1 deletion client/rpc-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ pub mod types;
mod eth;
mod eth_pubsub;
mod net;
#[cfg(feature = "txpool")]
mod txpool;
mod web3;

#[cfg(feature = "txpool")]
pub use self::txpool::TxPoolApiServer;
pub use self::{
eth::{EthApiServer, EthFilterApiServer},
eth_pubsub::EthPubSubApiServer,
net::NetApiServer,
txpool::TxPoolApiServer,
web3::Web3ApiServer,
};
3 changes: 2 additions & 1 deletion client/rpc-core/src/types/call_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@

use std::collections::BTreeMap;

use crate::types::{deserialize_data_or_input, Bytes};
use ethereum::AccessListItem;
use ethereum_types::{H160, H256, U256};
use serde::Deserialize;

use crate::types::{deserialize_data_or_input, Bytes};

/// Call request
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
Expand Down
4 changes: 3 additions & 1 deletion client/rpc-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ mod receipt;
mod sync;
mod transaction;
mod transaction_request;
#[cfg(feature = "txpool")]
mod txpool;
mod work;

pub mod pubsub;

use serde::{de::Error, Deserialize, Deserializer};

#[cfg(feature = "txpool")]
pub use self::txpool::{Get, Summary, TransactionMap, TxPoolResult, TxPoolTransaction};
pub use self::{
account_info::{AccountInfo, EthAccount, ExtAccountInfo, RecoveredAccount, StorageProof},
block::{Block, BlockTransactions, Header, Rich, RichBlock, RichHeader},
Expand All @@ -58,7 +61,6 @@ pub use self::{
},
transaction::{LocalTransactionStatus, RichRawTransaction, Transaction},
transaction_request::{TransactionMessage, TransactionRequest},
txpool::{Get, Summary, TransactionMap, TxPoolResult, TxPoolTransaction},
work::Work,
};

Expand Down
2 changes: 1 addition & 1 deletion client/rpc-core/src/types/txpool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::collections::HashMap;
use ethereum::{TransactionAction, TransactionV2 as EthereumTransaction};
use ethereum_types::{H160, H256, U256};
use serde::{Serialize, Serializer};
// Frontier

use crate::types::Bytes;

pub type TransactionMap<T> = HashMap<H160, HashMap<U256, T>>;
Expand Down
1 change: 1 addition & 0 deletions client/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ rocksdb = [
"fc-db/rocksdb",
"fc-mapping-sync/rocksdb",
]
txpool = ["fc-rpc-core/txpool"]
rpc-binary-search-estimate = []
69 changes: 46 additions & 23 deletions client/rpc/src/eth/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use ethereum_types::{H256, U256};
use jsonrpsee::core::{async_trait, RpcResult};
// Substrate
use sc_client_api::backend::{Backend, StorageProvider};
use sc_transaction_pool::ChainApi;
use sc_transaction_pool::{ChainApi, Pool};
use sc_transaction_pool_api::InPoolTransaction;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_core::hashing::keccak_256;
Expand All @@ -35,12 +36,12 @@ use sp_runtime::{
use fc_rpc_core::{types::*, EthFilterApiServer};
use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus};

use crate::{eth::cache::EthBlockDataCacheTask, frontier_backend_client, internal_err, TxPool};
use crate::{eth::cache::EthBlockDataCacheTask, frontier_backend_client, internal_err};

pub struct EthFilter<B: BlockT, C, BE, A: ChainApi> {
client: Arc<C>,
backend: Arc<dyn fc_db::BackendReader<B> + Send + Sync>,
tx_pool: TxPool<B, C, A>,
graph: Arc<Pool<A>>,
filter_pool: FilterPool,
max_stored_filters: usize,
max_past_logs: u32,
Expand All @@ -52,7 +53,7 @@ impl<B: BlockT, C, BE, A: ChainApi> EthFilter<B, C, BE, A> {
pub fn new(
client: Arc<C>,
backend: Arc<dyn fc_db::BackendReader<B> + Send + Sync>,
tx_pool: TxPool<B, C, A>,
graph: Arc<Pool<A>>,
filter_pool: FilterPool,
max_stored_filters: usize,
max_past_logs: u32,
Expand All @@ -61,7 +62,7 @@ impl<B: BlockT, C, BE, A: ChainApi> EthFilter<B, C, BE, A> {
Self {
client,
backend,
tx_pool,
graph,
filter_pool,
max_stored_filters,
max_past_logs,
Expand All @@ -80,8 +81,9 @@ where
A: ChainApi<Block = B> + 'static,
{
fn create_filter(&self, filter_type: FilterType) -> RpcResult<U256> {
let block_number =
UniqueSaturatedInto::<u64>::unique_saturated_into(self.client.info().best_number);
let info = self.client.info();
let best_hash = info.best_hash;
let best_number = UniqueSaturatedInto::<u64>::unique_saturated_into(info.best_number);
let pool = self.filter_pool.clone();
let response = if let Ok(locked) = &mut pool.lock() {
if locked.len() >= self.max_stored_filters {
Expand All @@ -97,24 +99,35 @@ where
Some((k, _)) => *k,
None => U256::zero(),
};

let pending_transaction_hashes = if let FilterType::PendingTransaction = filter_type {
self.tx_pool
.tx_pool_response()?
.ready
let txs_ready = self
.graph
.validated_pool()
.ready()
.map(|in_pool_tx| in_pool_tx.data().clone())
.collect();
// Use the runtime to match the (here) opaque extrinsics against ethereum transactions.
let api = self.client.runtime_api();
api.extrinsic_filter(best_hash, txs_ready)
.map_err(|err| {
internal_err(format!("fetch ready transactions failed: {err:?}"))
})?
.into_iter()
.map(|tx| tx.hash())
.collect()
.collect::<HashSet<_>>()
} else {
HashSet::new()
};

// Assume `max_stored_filters` is always < U256::max.
let key = last_key.checked_add(U256::one()).unwrap();
locked.insert(
key,
FilterPoolItem {
last_poll: BlockNumber::Num(block_number),
last_poll: BlockNumber::Num(best_number),
filter_type,
at_block: block_number,
at_block: best_number,
pending_transaction_hashes,
},
);
Expand Down Expand Up @@ -174,8 +187,9 @@ where
}

let key = U256::from(index.value());
let block_number =
UniqueSaturatedInto::<u64>::unique_saturated_into(self.client.info().best_number);
let info = self.client.info();
let best_hash = info.best_hash;
let best_number = UniqueSaturatedInto::<u64>::unique_saturated_into(info.best_number);
let pool = self.filter_pool.clone();
// Try to lock.
let path = if let Ok(locked) = &mut pool.lock() {
Expand All @@ -185,7 +199,7 @@ where
// For each block created since last poll, get a vector of ethereum hashes.
FilterType::Block => {
let last = pool_item.last_poll.to_min_block_num().unwrap();
let next = block_number + 1;
let next = best_number + 1;
// Update filter `last_poll`.
locked.insert(
key,
Expand All @@ -201,19 +215,28 @@ where
}
FilterType::PendingTransaction => {
let previous_hashes = pool_item.pending_transaction_hashes;
let current_hashes: HashSet<H256> = self
.tx_pool
.tx_pool_response()?
.ready
let txs_ready = self
.graph
.validated_pool()
.ready()
.map(|in_pool_tx| in_pool_tx.data().clone())
.collect();
// Use the runtime to match the (here) opaque extrinsics against ethereum transactions.
let api = self.client.runtime_api();
let current_hashes = api
.extrinsic_filter(best_hash, txs_ready)
.map_err(|err| {
internal_err(format!("fetch ready transactions failed: {err:?}"))
})?
.into_iter()
.map(|tx| tx.hash())
.collect();
.collect::<HashSet<_>>();

// Update filter `last_poll`.
locked.insert(
key,
FilterPoolItem {
last_poll: BlockNumber::Num(block_number + 1),
last_poll: BlockNumber::Num(best_number + 1),
filter_type: pool_item.filter_type.clone(),
at_block: pool_item.at_block,
pending_transaction_hashes: current_hashes.clone(),
Expand All @@ -233,7 +256,7 @@ where
locked.insert(
key,
FilterPoolItem {
last_poll: BlockNumber::Num(block_number + 1),
last_poll: BlockNumber::Num(best_number + 1),
filter_type: pool_item.filter_type.clone(),
at_block: pool_item.at_block,
pending_transaction_hashes: HashSet::new(),
Expand Down
10 changes: 6 additions & 4 deletions client/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,24 @@ mod eth;
mod eth_pubsub;
mod net;
mod signer;
#[cfg(feature = "txpool")]
mod txpool;
mod web3;

#[cfg(feature = "txpool")]
pub use self::txpool::TxPool;
pub use self::{
eth::{format, EstimateGasAdapter, Eth, EthBlockDataCacheTask, EthConfig, EthFilter, EthTask},
eth_pubsub::{EthPubSub, EthereumSubIdProvider},
net::Net,
signer::{EthDevSigner, EthSigner},
txpool::TxPool,
web3::Web3,
};

pub use ethereum::TransactionV2 as EthereumTransaction;
#[cfg(feature = "txpool")]
pub use fc_rpc_core::TxPoolApiServer;
pub use fc_rpc_core::{
EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, TxPoolApiServer,
Web3ApiServer,
EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, Web3ApiServer,
};
pub use fc_storage::{
OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override,
Expand Down
2 changes: 2 additions & 0 deletions template/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ default = [
"with-rocksdb-weights",
"rocksdb",
"sql",
"txpool",
]
rocksdb = [
"sc-cli/rocksdb",
Expand All @@ -105,6 +106,7 @@ sql = [
]
with-rocksdb-weights = ["frontier-template-runtime/with-rocksdb-weights"]
with-paritydb-weights = ["frontier-template-runtime/with-paritydb-weights"]
txpool = ["fc-rpc/txpool"]
rpc-binary-search-estimate = ["fc-rpc/rpc-binary-search-estimate"]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
Expand Down
15 changes: 9 additions & 6 deletions template/node/src/rpc/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use sp_core::H256;
use sp_runtime::traits::Block as BlockT;
// Frontier
pub use fc_rpc::{EthBlockDataCacheTask, EthConfig, OverrideHandle, StorageOverride, TxPool};
pub use fc_rpc::{EthBlockDataCacheTask, EthConfig, OverrideHandle, StorageOverride};
pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};
pub use fc_storage::overrides_handle;
use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi};
Expand Down Expand Up @@ -109,8 +109,10 @@ where
{
use fc_rpc::{
Eth, EthApiServer, EthDevSigner, EthFilter, EthFilterApiServer, EthPubSub,
EthPubSubApiServer, EthSigner, Net, NetApiServer, TxPoolApiServer, Web3, Web3ApiServer,
EthPubSubApiServer, EthSigner, Net, NetApiServer, Web3, Web3ApiServer,
};
#[cfg(feature = "txpool")]
use fc_rpc::{TxPool, TxPoolApiServer};

let EthDeps {
client,
Expand Down Expand Up @@ -158,13 +160,12 @@ where
.into_rpc(),
)?;

let tx_pool = TxPool::new(client.clone(), graph);
if let Some(filter_pool) = filter_pool {
io.merge(
EthFilter::new(
client.clone(),
frontier_backend,
tx_pool.clone(),
graph.clone(),
filter_pool,
500_usize, // max stored filters
max_past_logs,
Expand Down Expand Up @@ -196,8 +197,10 @@ where
.into_rpc(),
)?;

io.merge(Web3::new(client).into_rpc())?;
io.merge(tx_pool.into_rpc())?;
io.merge(Web3::new(client.clone()).into_rpc())?;

#[cfg(feature = "txpool")]
io.merge(TxPool::new(client, graph).into_rpc())?;

Ok(io)
}

0 comments on commit 22277c2

Please sign in to comment.