From d42806db329568893bb78e63db16c04baede41b4 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Thu, 3 Mar 2022 14:18:23 +0800 Subject: [PATCH] Improve fc-rpc (#593) * Split net api and web3 api into their own modules Signed-off-by: koushiro * some nits Signed-off-by: koushiro * remove some useless trait bound Signed-off-by: koushiro --- Cargo.lock | 2 +- client/rpc-core/src/eth.rs | 1 + client/rpc-core/src/lib.rs | 10 +- client/rpc-core/src/net.rs | 4 +- client/rpc-core/src/web3.rs | 1 + client/rpc/Cargo.toml | 24 ++-- client/rpc/src/eth.rs | 230 ++++++++--------------------------- client/rpc/src/eth_pubsub.rs | 59 ++++----- client/rpc/src/lib.rs | 60 ++++----- client/rpc/src/net.rs | 80 ++++++++++++ client/rpc/src/web3.rs | 73 +++++++++++ 11 files changed, 275 insertions(+), 269 deletions(-) create mode 100644 client/rpc/src/net.rs create mode 100644 client/rpc/src/web3.rs diff --git a/Cargo.lock b/Cargo.lock index 9203563df9..5068d04f08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1590,10 +1590,10 @@ dependencies = [ "sc-service", "sc-transaction-pool", "sc-transaction-pool-api", - "sha3 0.10.0", "sp-api", "sp-block-builder", "sp-blockchain", + "sp-core", "sp-io", "sp-runtime", "sp-storage", diff --git a/client/rpc-core/src/eth.rs b/client/rpc-core/src/eth.rs index 758ffd713f..628bc1247d 100644 --- a/client/rpc-core/src/eth.rs +++ b/client/rpc-core/src/eth.rs @@ -26,6 +26,7 @@ use crate::types::{ BlockNumber, Bytes, CallRequest, FeeHistory, Filter, FilterChanges, Index, Log, Receipt, RichBlock, SyncStatus, Transaction, TransactionRequest, Work, }; + pub use rpc_impl_EthApi::gen_server::EthApi as EthApiServer; pub use rpc_impl_EthFilterApi::gen_server::EthFilterApi as EthFilterApiServer; diff --git a/client/rpc-core/src/lib.rs b/client/rpc-core/src/lib.rs index dcf0e174ef..913fa4044e 100644 --- a/client/rpc-core/src/lib.rs +++ b/client/rpc-core/src/lib.rs @@ -23,7 +23,9 @@ mod eth_pubsub; mod net; mod web3; -pub use eth::{EthApi, EthApiServer, EthFilterApi, EthFilterApiServer}; -pub use eth_pubsub::{EthPubSubApi, EthPubSubApiServer}; -pub use net::{NetApi, NetApiServer}; -pub use web3::{Web3Api, Web3ApiServer}; +pub use self::{ + eth::{EthApi, EthApiServer, EthFilterApi, EthFilterApiServer}, + eth_pubsub::{EthPubSubApi, EthPubSubApiServer}, + net::{NetApi, NetApiServer}, + web3::{Web3Api, Web3ApiServer}, +}; diff --git a/client/rpc-core/src/net.rs b/client/rpc-core/src/net.rs index 1bc5f03eea..e207abb3e1 100644 --- a/client/rpc-core/src/net.rs +++ b/client/rpc-core/src/net.rs @@ -17,10 +17,12 @@ // along with this program. If not, see . //! Net rpc interface. -use crate::types::PeerCount; + use jsonrpc_core::Result; use jsonrpc_derive::rpc; +use crate::types::PeerCount; + pub use rpc_impl_NetApi::gen_server::NetApi as NetApiServer; /// Net rpc interface. diff --git a/client/rpc-core/src/web3.rs b/client/rpc-core/src/web3.rs index c957d1a839..90d755fb84 100644 --- a/client/rpc-core/src/web3.rs +++ b/client/rpc-core/src/web3.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . //! Web3 rpc interface. + use ethereum_types::H256; use jsonrpc_core::Result; use jsonrpc_derive::rpc; diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 6f459975ac..08553e7f53 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -20,22 +20,22 @@ jsonrpc-core-client = "18.0" jsonrpc-pubsub = "18.0" rand = "0.8" rlp = "0.5" -sha3 = "0.10" tokio = { version = "1.14", features = [ "sync" ] } codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sp-block-builder = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-block-builder = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } -sp-storage = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-service = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-storage = { version = "5.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-service = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } fp-rpc = { version = "3.0.0-dev", path = "../../primitives/rpc" } fp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } diff --git a/client/rpc/src/eth.rs b/client/rpc/src/eth.rs index 97559a5191..4cbaf41b65 100644 --- a/client/rpc/src/eth.rs +++ b/client/rpc/src/eth.rs @@ -16,25 +16,22 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use codec::{Decode, Encode}; +use std::{ + collections::{BTreeMap, HashMap}, + marker::PhantomData, + sync::{Arc, Mutex}, + time, +}; + use ethereum::{BlockV2 as EthereumBlock, TransactionV2 as EthereumTransaction}; use ethereum_types::{H160, H256, H512, H64, U256, U64}; use evm::{ExitError, ExitReason}; -use fc_rpc_core::{ - types::{ - Block, BlockNumber, BlockTransactions, Bytes, CallRequest, FeeHistory, FeeHistoryCache, - FeeHistoryCacheItem, Filter, FilterChanges, FilterPool, FilterPoolItem, FilterType, - FilteredParams, Header, Index, Log, PeerCount, Receipt, Rich, RichBlock, SyncInfo, - SyncStatus, Transaction, TransactionMessage, TransactionRequest, Work, - }, - EthApi as EthApiT, EthFilterApi as EthFilterApiT, NetApi as NetApiT, Web3Api as Web3ApiT, -}; -pub use fc_rpc_core::{EthApiServer, EthFilterApiServer, NetApiServer, Web3ApiServer}; -use fp_rpc::{ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi, TransactionStatus}; -use fp_storage::EthereumStorageSchema; use futures::{future::TryFutureExt, StreamExt}; use jsonrpc_core::{futures::future, BoxFuture, Result}; use lru::LruCache; +use tokio::sync::{mpsc, oneshot}; + +use codec::{Decode, Encode}; use sc_client_api::{ backend::{Backend, StateBackend, StorageProvider}, client::BlockchainEvents, @@ -43,21 +40,26 @@ use sc_network::{ExHashT, NetworkService}; use sc_service::SpawnTaskHandle; use sc_transaction_pool::{ChainApi, Pool}; use sc_transaction_pool_api::{InPoolTransaction, TransactionPool}; -use sha3::{Digest, Keccak256}; use sp_api::{ApiExt, BlockId, Core, HeaderT, ProvideRuntimeApi}; use sp_block_builder::BlockBuilder; -use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sp_blockchain::HeaderBackend; +use sp_core::hashing::keccak_256; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, NumberFor, One, Saturating, UniqueSaturatedInto, Zero}, transaction_validity::TransactionSource, }; -use std::{ - collections::{BTreeMap, HashMap}, - marker::PhantomData, - sync::{Arc, Mutex}, - time, + +use fc_rpc_core::{ + types::{ + Block, BlockNumber, BlockTransactions, Bytes, CallRequest, FeeHistory, FeeHistoryCache, + FeeHistoryCacheItem, Filter, FilterChanges, FilterPool, FilterPoolItem, FilterType, + FilteredParams, Header, Index, Log, Receipt, Rich, RichBlock, SyncInfo, SyncStatus, + Transaction, TransactionMessage, TransactionRequest, Work, + }, + EthApi as EthApiT, EthFilterApi as EthFilterApiT, }; -use tokio::sync::{mpsc, oneshot}; +use fp_rpc::{ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi, TransactionStatus}; +use fp_storage::EthereumStorageSchema; use crate::{ error_on_execution_failure, frontier_backend_client, internal_err, overrides::OverrideHandle, @@ -81,17 +83,7 @@ pub struct EthApi { _marker: PhantomData<(B, BE)>, } -impl EthApi -where - C: ProvideRuntimeApi, - C::Api: sp_api::ApiExt - + BlockBuilder - + ConvertTransactionRuntimeApi - + EthereumRuntimeRPCApi, - B: BlockT + Send + Sync + 'static, - A: ChainApi + 'static, - C: Send + Sync + 'static, -{ +impl EthApi { pub fn new( client: Arc, pool: Arc

, @@ -137,9 +129,9 @@ fn rich_block_build( Rich { inner: Block { header: Header { - hash: Some(hash.unwrap_or_else(|| { - H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()) - })), + hash: Some( + hash.unwrap_or_else(|| H256::from(keccak_256(&rlp::encode(&block.header)))), + ), parent_hash: block.header.parent_hash, uncles_hash: block.header.ommers_hash, author: block.header.beneficiary, @@ -238,9 +230,7 @@ fn transaction_build( // Block hash. transaction.block_hash = block.as_ref().map_or(None, |block| { - Some(H256::from_slice( - Keccak256::digest(&rlp::encode(&block.header)).as_slice(), - )) + Some(H256::from(keccak_256(&rlp::encode(&block.header)))) }); // Block number. transaction.block_number = block.as_ref().map(|block| block.header.number); @@ -254,7 +244,7 @@ fn transaction_build( transaction.from = status.as_ref().map_or( { match pubkey { - Some(pk) => H160::from(H256::from_slice(Keccak256::digest(&pk).as_slice())), + Some(pk) => H160::from(H256::from(keccak_256(&pk))), _ => H160::default(), } }, @@ -290,15 +280,13 @@ fn pending_runtime_api<'a, B: BlockT, C, BE, A: ChainApi>( graph: &'a Pool, ) -> Result> where + B: BlockT + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider, - C: HeaderBackend + HeaderMetadata + 'static, - C::Api: EthereumRuntimeRPCApi, - C::Api: BlockBuilder, + C: HeaderBackend + Send + Sync + 'static, + C::Api: BlockBuilder + EthereumRuntimeRPCApi, BE: Backend + 'static, BE::State: StateBackend, - B: BlockT + Send + Sync + 'static, A: ChainApi + 'static, - C: Send + Sync + 'static, { // In case of Pending, we need an overlayed state to query over. let api = client.runtime_api(); @@ -331,13 +319,12 @@ async fn filter_range_logs( to: NumberFor, ) -> Result<()> where + B: BlockT + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider, - C: HeaderBackend + HeaderMetadata + 'static, + C: HeaderBackend + Send + Sync + 'static, C::Api: EthereumRuntimeRPCApi, BE: Backend + 'static, BE::State: StateBackend, - B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, { // Max request duration of 10 seconds. let max_duration = time::Duration::from_secs(10); @@ -446,7 +433,7 @@ fn filter_block_logs<'a>( ) -> &'a Vec { let params = FilteredParams::new(Some(filter.clone())); let mut block_log_index: u32 = 0; - let block_hash = H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()); + let block_hash = H256::from(keccak_256(&rlp::encode(&block.header))); for status in transaction_statuses.iter() { let logs = status.logs.clone(); let mut transaction_log_index: u32 = 0; @@ -536,16 +523,12 @@ fn fee_details( impl EthApiT for EthApi where + B: BlockT + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider, - C: HeaderBackend + HeaderMetadata + 'static, - C::Api: sp_api::ApiExt - + BlockBuilder - + ConvertTransactionRuntimeApi - + EthereumRuntimeRPCApi, + C: HeaderBackend + Send + Sync + 'static, + C::Api: BlockBuilder + ConvertTransactionRuntimeApi + EthereumRuntimeRPCApi, BE: Backend + 'static, BE::State: StateBackend, - B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, P: TransactionPool + Send + Sync + 'static, A: ChainApi + 'static, CT: fp_rpc::ConvertTransaction<::Extrinsic> + Send + Sync + 'static, @@ -778,8 +761,7 @@ where match (block, statuses) { (Some(block), Some(statuses)) => { - let hash = - H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()); + let hash = H256::from(keccak_256(&rlp::encode(&block.header))); Ok(Some(rich_block_build( block, @@ -2088,8 +2070,7 @@ where match (block, statuses, receipts) { (Some(block), Some(statuses), Some(receipts)) => { - let block_hash = - H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()); + let block_hash = H256::from(keccak_256(&rlp::encode(&block.header))); let receipt = receipts[index].clone(); let (logs, logs_bloom, status_code, cumulative_gas_used, gas_used) = @@ -2212,7 +2193,7 @@ where .collect() }, status_code: Some(U64::from(status_code)), - logs_bloom: logs_bloom, + logs_bloom, state_root: None, effective_gas_price, })); @@ -2448,107 +2429,6 @@ where } } -pub struct NetApi { - client: Arc, - network: Arc>, - peer_count_as_hex: bool, - _marker: PhantomData, -} - -impl NetApi { - pub fn new( - client: Arc, - network: Arc>, - peer_count_as_hex: bool, - ) -> Self { - Self { - client, - network, - peer_count_as_hex, - _marker: PhantomData, - } - } -} - -impl NetApiT for NetApi -where - C: ProvideRuntimeApi + StorageProvider, - C: HeaderBackend + HeaderMetadata + 'static, - C::Api: EthereumRuntimeRPCApi, - BE: Backend + 'static, - BE::State: StateBackend, - C: Send + Sync + 'static, - B: BlockT + Send + Sync + 'static, -{ - fn version(&self) -> Result { - let hash = self.client.info().best_hash; - Ok(self - .client - .runtime_api() - .chain_id(&BlockId::Hash(hash)) - .map_err(|_| internal_err("fetch runtime chain id failed"))? - .to_string()) - } - - fn peer_count(&self) -> Result { - let peer_count = self.network.num_connected(); - Ok(match self.peer_count_as_hex { - true => PeerCount::String(format!("0x{:x}", peer_count)), - false => PeerCount::U32(peer_count as u32), - }) - } - - fn is_listening(&self) -> Result { - Ok(true) - } -} - -pub struct Web3Api { - client: Arc, - _marker: PhantomData, -} - -impl Web3Api { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: PhantomData, - } - } -} - -impl Web3ApiT for Web3Api -where - C: ProvideRuntimeApi, - C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, - B: BlockT + Send + Sync + 'static, -{ - fn client_version(&self) -> Result { - let hash = self.client.info().best_hash; - let version = self - .client - .runtime_api() - .version(&BlockId::Hash(hash)) - .map_err(|err| internal_err(format!("fetch runtime version failed: {:?}", err)))?; - Ok(format!( - "{spec_name}/v{spec_version}.{impl_version}/{pkg_name}-{pkg_version}", - spec_name = version.spec_name, - spec_version = version.spec_version, - impl_version = version.impl_version, - pkg_name = env!("CARGO_PKG_NAME"), - pkg_version = env!("CARGO_PKG_VERSION") - )) - } - - fn sha3(&self, input: Bytes) -> Result { - Ok(H256::from_slice( - Keccak256::digest(&input.into_vec()).as_slice(), - )) - } -} - pub struct EthFilterApi { client: Arc, backend: Arc>, @@ -2556,18 +2436,10 @@ pub struct EthFilterApi { max_stored_filters: usize, max_past_logs: u32, block_data_cache: Arc>, - _marker: PhantomData<(B, BE)>, + _marker: PhantomData, } -impl EthFilterApi -where - C: ProvideRuntimeApi + StorageProvider, - C::Api: EthereumRuntimeRPCApi, - B: BlockT + Send + Sync + 'static, - BE: Backend + 'static, - BE::State: StateBackend, - C: Send + Sync + 'static, -{ +impl EthFilterApi { pub fn new( client: Arc, backend: Arc>, @@ -2590,13 +2462,8 @@ where impl EthFilterApi where - C: ProvideRuntimeApi + StorageProvider, - C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, B: BlockT + Send + Sync + 'static, - BE: Backend + 'static, - BE::State: StateBackend, + C: HeaderBackend + Send + Sync + 'static, { fn create_filter(&self, filter_type: FilterType) -> Result { let block_number = @@ -2633,11 +2500,10 @@ where impl EthFilterApiT for EthFilterApi where + B: BlockT + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider, + C: HeaderBackend + Send + Sync + 'static, C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, - B: BlockT + Send + Sync + 'static, BE: Backend + 'static, BE::State: StateBackend, { @@ -2903,10 +2769,10 @@ pub struct EthTask(PhantomData<(B, C, BE)>); impl EthTask where - C: ProvideRuntimeApi + BlockchainEvents + HeaderBackend + StorageProvider, B: BlockT, + C: ProvideRuntimeApi + StorageProvider + BlockchainEvents, + C: HeaderBackend + Send + Sync + 'static, C::Api: EthereumRuntimeRPCApi, - C: Send + Sync + 'static, BE: Backend + 'static, BE::State: StateBackend, { diff --git a/client/rpc/src/eth_pubsub.rs b/client/rpc/src/eth_pubsub.rs index a54f10c167..62532b9703 100644 --- a/client/rpc/src/eth_pubsub.rs +++ b/client/rpc/src/eth_pubsub.rs @@ -16,42 +16,40 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use std::{collections::BTreeMap, iter, marker::PhantomData, sync::Arc}; + +use ethereum::BlockV2 as EthereumBlock; +use ethereum_types::{H256, U256}; +use futures::{FutureExt as _, SinkExt as _, StreamExt as _}; +use jsonrpc_core::Result as JsonRpcResult; +use jsonrpc_pubsub::{ + manager::{IdProvider, SubscriptionManager}, + typed::Subscriber, + SubscriptionId, +}; use log::warn; use rand::{distributions::Alphanumeric, thread_rng, Rng}; + use sc_client_api::{ backend::{Backend, StateBackend, StorageProvider}, client::BlockchainEvents, }; +use sc_network::{ExHashT, NetworkService}; use sc_rpc::Metadata; use sc_transaction_pool_api::TransactionPool; use sp_api::{BlockId, ProvideRuntimeApi}; -use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sp_blockchain::HeaderBackend; +use sp_core::hashing::keccak_256; use sp_runtime::traits::{BlakeTwo256, Block as BlockT, UniqueSaturatedInto}; -use std::{collections::BTreeMap, iter, marker::PhantomData, sync::Arc}; -use ethereum::BlockV2 as EthereumBlock; -use ethereum_types::{H256, U256}; use fc_rpc_core::{ types::{ pubsub::{Kind, Params, PubSubSyncStatus, Result as PubSubResult}, Bytes, FilteredParams, Header, Log, Rich, }, - EthPubSubApi::{self as EthPubSubApiT}, + EthPubSubApi as EthPubSubApiT, }; -use jsonrpc_pubsub::{ - manager::{IdProvider, SubscriptionManager}, - typed::Subscriber, - SubscriptionId, -}; -use sha3::{Digest, Keccak256}; - -pub use fc_rpc_core::EthPubSubApiServer; -use futures::{FutureExt as _, SinkExt as _, StreamExt as _}; - use fp_rpc::EthereumRuntimeRPCApi; -use jsonrpc_core::Result as JsonRpcResult; - -use sc_network::{ExHashT, NetworkService}; use crate::{frontier_backend_client, overrides::OverrideHandle}; @@ -86,16 +84,10 @@ pub struct EthPubSubApi { network: Arc>, subscriptions: SubscriptionManager, overrides: Arc>, - _marker: PhantomData<(B, BE)>, + _marker: PhantomData, } -impl EthPubSubApi -where - B: BlockT + Send + Sync + 'static, - C: ProvideRuntimeApi, - C::Api: EthereumRuntimeRPCApi, - C: Send + Sync + 'static, -{ +impl EthPubSubApi { pub fn new( pool: Arc

, client: Arc, @@ -122,9 +114,7 @@ impl SubscriptionResult { pub fn new_heads(&self, block: EthereumBlock) -> PubSubResult { PubSubResult::Header(Box::new(Rich { inner: Header { - hash: Some(H256::from_slice( - Keccak256::digest(&rlp::encode(&block.header)).as_slice(), - )), + hash: Some(H256::from(keccak_256(&rlp::encode(&block.header)))), parent_hash: block.header.parent_hash, uncles_hash: block.header.ommers_hash, author: block.header.beneficiary, @@ -154,9 +144,7 @@ impl SubscriptionResult { receipts: Vec, params: &FilteredParams, ) -> Vec { - let block_hash = Some(H256::from_slice( - Keccak256::digest(&rlp::encode(&block.header)).as_slice(), - )); + let block_hash = Some(H256::from(keccak_256(&rlp::encode(&block.header)))); let mut logs: Vec = vec![]; let mut log_index: u32 = 0; for (receipt_index, receipt) in receipts.into_iter().enumerate() { @@ -177,9 +165,9 @@ impl SubscriptionResult { address: log.address, topics: log.topics, data: Bytes(log.data), - block_hash: block_hash, + block_hash, block_number: Some(block.header.number), - transaction_hash: transaction_hash, + transaction_hash, transaction_index: Some(U256::from(receipt_index)), log_index: Some(U256::from(log_index)), transaction_log_index: Some(U256::from(transaction_log_index)), @@ -231,8 +219,7 @@ where B: BlockT + Send + Sync + 'static, P: TransactionPool + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider + BlockchainEvents, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, C::Api: EthereumRuntimeRPCApi, BE: Backend + 'static, BE::State: StateBackend, diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 30cfcc439c..e9b956788d 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -18,43 +18,48 @@ mod eth; mod eth_pubsub; +mod net; mod overrides; +mod web3; pub use self::{ - eth::{ - EthApi, EthApiServer, EthBlockDataCache, EthFilterApi, EthFilterApiServer, EthTask, NetApi, - NetApiServer, Web3Api, Web3ApiServer, - }, - eth_pubsub::{EthPubSubApi, EthPubSubApiServer, HexEncodedIdProvider}, + eth::{EthApi, EthBlockDataCache, EthFilterApi, EthTask}, + eth_pubsub::{EthPubSubApi, HexEncodedIdProvider}, + net::NetApi, overrides::{ OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override, SchemaV3Override, StorageOverride, }, + web3::Web3Api, }; pub use ethereum::TransactionV2 as EthereumTransaction; use ethereum_types::{H160, H256}; use evm::{ExitError, ExitReason}; -pub use fc_rpc_core::types::TransactionMessage; +pub use fc_rpc_core::{ + types::TransactionMessage, EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, + Web3ApiServer, +}; use jsonrpc_core::{Error, ErrorCode, Value}; -use sha3::{Digest, Keccak256}; +use sp_core::hashing::keccak_256; pub mod frontier_backend_client { use super::internal_err; - use fc_rpc_core::types::BlockNumber; - use fp_storage::PALLET_ETHEREUM_SCHEMA; + use codec::Decode; + use ethereum_types::H256; + use jsonrpc_core::Result as RpcResult; + use sc_client_api::backend::{Backend, StateBackend, StorageProvider}; - use sp_api::{BlockId, HeaderT}; use sp_blockchain::HeaderBackend; - use sp_runtime::traits::{BlakeTwo256, Block as BlockT, UniqueSaturatedInto, Zero}; + use sp_runtime::{ + generic::BlockId, + traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, UniqueSaturatedInto, Zero}, + }; use sp_storage::StorageKey; - use codec::Decode; - use jsonrpc_core::Result as RpcResult; - - use ethereum_types::H256; - use fp_storage::EthereumStorageSchema; + use fc_rpc_core::types::BlockNumber; + use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; pub fn native_block_id( client: &C, @@ -62,10 +67,8 @@ pub mod frontier_backend_client { number: Option, ) -> RpcResult>> where - B: BlockT, - C: HeaderBackend + 'static, B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, { Ok(match number.unwrap_or(BlockNumber::Latest) { BlockNumber::Hash { hash, .. } => load_hash::(backend, hash).unwrap_or(None), @@ -81,7 +84,6 @@ pub mod frontier_backend_client { hash: H256, ) -> RpcResult>> where - B: BlockT, B: BlockT + Send + Sync + 'static, { let substrate_hash = backend @@ -99,7 +101,6 @@ pub mod frontier_backend_client { backend: &fc_db::Backend, ) -> RpcResult>> where - B: BlockT, B: BlockT + Send + Sync + 'static, { let cache = backend @@ -114,7 +115,6 @@ pub mod frontier_backend_client { new_cache: Vec<(EthereumStorageSchema, H256)>, ) -> RpcResult<()> where - B: BlockT, B: BlockT + Send + Sync + 'static, { backend @@ -129,12 +129,10 @@ pub mod frontier_backend_client { at: BlockId, ) -> EthereumStorageSchema where - B: BlockT, - C: StorageProvider, + B: BlockT + Send + Sync + 'static, + C: StorageProvider + Send + Sync + 'static, BE: Backend + 'static, BE::State: StateBackend, - B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, { match client.storage(&at, &StorageKey(PALLET_ETHEREUM_SCHEMA.to_vec())) { Ok(Some(bytes)) => Decode::decode(&mut &bytes.0[..]) @@ -146,10 +144,8 @@ pub mod frontier_backend_client { pub fn is_canon(client: &C, target_hash: H256) -> bool where - B: BlockT, - C: HeaderBackend + 'static, B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, { if let Ok(Some(number)) = client.number(target_hash) { if let Ok(Some(header)) = client.header(BlockId::Number(number)) { @@ -166,10 +162,8 @@ pub mod frontier_backend_client { only_canonical: bool, ) -> RpcResult> where - B: BlockT, - C: HeaderBackend + 'static, B: BlockT + Send + Sync + 'static, - C: Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, { let transaction_metadata = backend .mapping() @@ -309,7 +303,7 @@ fn secret_key_address(secret: &libsecp256k1::SecretKey) -> H160 { fn public_key_address(public: &libsecp256k1::PublicKey) -> H160 { let mut res = [0u8; 64]; res.copy_from_slice(&public.serialize()[1..65]); - H160::from(H256::from_slice(Keccak256::digest(&res).as_slice())) + H160::from(H256::from(keccak_256(&res))) } impl EthSigner for EthDevSigner { diff --git a/client/rpc/src/net.rs b/client/rpc/src/net.rs new file mode 100644 index 0000000000..3866b74eab --- /dev/null +++ b/client/rpc/src/net.rs @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::sync::Arc; + +use ethereum_types::H256; +use jsonrpc_core::Result; +use sc_network::{ExHashT, NetworkService}; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; + +use fc_rpc_core::{types::PeerCount, NetApi as NetApiT}; +use fp_rpc::EthereumRuntimeRPCApi; + +use crate::internal_err; + +pub struct NetApi { + client: Arc, + network: Arc>, + peer_count_as_hex: bool, +} + +impl NetApi { + pub fn new( + client: Arc, + network: Arc>, + peer_count_as_hex: bool, + ) -> Self { + Self { + client, + network, + peer_count_as_hex, + } + } +} + +impl NetApiT for NetApi +where + B: BlockT + Send + Sync + 'static, + C: HeaderBackend + ProvideRuntimeApi + Send + Sync + 'static, + C::Api: EthereumRuntimeRPCApi, +{ + fn version(&self) -> Result { + let hash = self.client.info().best_hash; + Ok(self + .client + .runtime_api() + .chain_id(&BlockId::Hash(hash)) + .map_err(|_| internal_err("fetch runtime chain id failed"))? + .to_string()) + } + + fn peer_count(&self) -> Result { + let peer_count = self.network.num_connected(); + Ok(match self.peer_count_as_hex { + true => PeerCount::String(format!("0x{:x}", peer_count)), + false => PeerCount::U32(peer_count as u32), + }) + } + + fn is_listening(&self) -> Result { + Ok(true) + } +} diff --git a/client/rpc/src/web3.rs b/client/rpc/src/web3.rs new file mode 100644 index 0000000000..e170674d87 --- /dev/null +++ b/client/rpc/src/web3.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{marker::PhantomData, sync::Arc}; + +use ethereum_types::H256; +use jsonrpc_core::Result; +use sp_api::{Core, ProvideRuntimeApi}; +use sp_blockchain::HeaderBackend; +use sp_core::keccak_256; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; + +use fc_rpc_core::{types::Bytes, Web3Api as Web3ApiT}; +use fp_rpc::EthereumRuntimeRPCApi; + +use crate::internal_err; + +pub struct Web3Api { + client: Arc, + _marker: PhantomData, +} + +impl Web3Api { + pub fn new(client: Arc) -> Self { + Self { + client, + _marker: PhantomData, + } + } +} + +impl Web3ApiT for Web3Api +where + B: BlockT + Send + Sync + 'static, + C: HeaderBackend + ProvideRuntimeApi + Send + Sync + 'static, + C::Api: EthereumRuntimeRPCApi, +{ + fn client_version(&self) -> Result { + let hash = self.client.info().best_hash; + let version = self + .client + .runtime_api() + .version(&BlockId::Hash(hash)) + .map_err(|err| internal_err(format!("fetch runtime version failed: {:?}", err)))?; + Ok(format!( + "{spec_name}/v{spec_version}.{impl_version}/{pkg_name}-{pkg_version}", + spec_name = version.spec_name, + spec_version = version.spec_version, + impl_version = version.impl_version, + pkg_name = env!("CARGO_PKG_NAME"), + pkg_version = env!("CARGO_PKG_VERSION") + )) + } + + fn sha3(&self, input: Bytes) -> Result { + Ok(H256::from(keccak_256(&input.into_vec()))) + } +}