Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -89,6 +89,7 @@ default = [
"with-rocksdb-weights",
"rocksdb",
"sql",
"txpool",
]
rocksdb = [
"sc-cli/rocksdb",
Expand All @@ -104,6 +105,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)
}