From bd0891384e03a6bc6347251e1f45454635a9dbba Mon Sep 17 00:00:00 2001 From: tgmichel Date: Sat, 21 Nov 2020 18:36:46 +0100 Subject: [PATCH] Implement `Web3Api` (#205) * Implement Web3Api * Add Web3Api tests * Fix checker * Fix test --- client/rpc-core/src/lib.rs | 2 +- client/rpc-core/src/web3.rs | 2 ++ client/rpc/src/eth.rs | 50 ++++++++++++++++++++++++++++++++-- client/rpc/src/lib.rs | 2 +- template/node/src/rpc.rs | 9 +++++- ts-tests/tests/test-web3api.ts | 18 ++++++++++++ 6 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 ts-tests/tests/test-web3api.ts diff --git a/client/rpc-core/src/lib.rs b/client/rpc-core/src/lib.rs index 41d3f8a7c..ad7fcc595 100644 --- a/client/rpc-core/src/lib.rs +++ b/client/rpc-core/src/lib.rs @@ -26,4 +26,4 @@ mod web3; pub use eth::{EthApi, EthApiServer, EthFilterApi}; pub use eth_pubsub::{EthPubSubApi, EthPubSubApiServer}; pub use net::{NetApi, NetApiServer}; -pub use web3::Web3Api; +pub use web3::{Web3Api, Web3ApiServer}; diff --git a/client/rpc-core/src/web3.rs b/client/rpc-core/src/web3.rs index 396ddd5ca..c957d1a83 100644 --- a/client/rpc-core/src/web3.rs +++ b/client/rpc-core/src/web3.rs @@ -23,6 +23,8 @@ use jsonrpc_derive::rpc; use crate::types::Bytes; +pub use rpc_impl_Web3Api::gen_server::Web3Api as Web3ApiServer; + /// Web3 rpc interface. #[rpc(server)] pub trait Web3Api { diff --git a/client/rpc/src/eth.rs b/client/rpc/src/eth.rs index 19f1778d8..e5c7f307c 100644 --- a/client/rpc/src/eth.rs +++ b/client/rpc/src/eth.rs @@ -29,13 +29,13 @@ use sp_runtime::{ traits::{Block as BlockT, UniqueSaturatedInto, Zero, One, Saturating, BlakeTwo256}, transaction_validity::TransactionSource }; -use sp_api::{ProvideRuntimeApi, BlockId}; +use sp_api::{ProvideRuntimeApi, BlockId, Core}; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; use sc_client_api::backend::{StorageProvider, Backend, StateBackend, AuxStore}; use sha3::{Keccak256, Digest}; use sp_blockchain::{Error as BlockChainError, HeaderMetadata, HeaderBackend}; use sc_network::{NetworkService, ExHashT}; -use fc_rpc_core::{EthApi as EthApiT, NetApi as NetApiT}; +use fc_rpc_core::{EthApi as EthApiT, NetApi as NetApiT, Web3Api as Web3ApiT}; use fc_rpc_core::types::{ BlockNumber, Bytes, CallRequest, Filter, FilteredParams, Index, Log, Receipt, RichBlock, SyncStatus, SyncInfo, Transaction, Work, Rich, Block, BlockTransactions, VariadicValue, @@ -44,7 +44,7 @@ use fc_rpc_core::types::{ use fp_rpc::{EthereumRuntimeRPCApi, ConvertTransaction, TransactionStatus}; use crate::{internal_err, error_on_execution_failure, EthSigner}; -pub use fc_rpc_core::{EthApiServer, NetApiServer}; +pub use fc_rpc_core::{EthApiServer, NetApiServer, Web3ApiServer}; use codec::{self, Encode}; pub struct EthApi { @@ -1077,3 +1077,47 @@ impl NetApiT for NetApi where .map_err(|_| internal_err("fetch runtime chain id failed"))?.to_string()) } } + +pub struct Web3Api { + client: Arc, + _marker: PhantomData, +} + +impl Web3Api { + pub fn new( + client: Arc, + ) -> Self { + Self { + client: client, + _marker: PhantomData, + } + } +} + +impl Web3ApiT for Web3Api where + C: ProvideRuntimeApi + AuxStore, + 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() + )) + } +} diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 6e5734baa..f7e07eaed 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -19,7 +19,7 @@ mod eth; mod eth_pubsub; -pub use eth::{EthApi, EthApiServer, NetApi, NetApiServer}; +pub use eth::{EthApi, EthApiServer, NetApi, NetApiServer, Web3Api, Web3ApiServer}; pub use eth_pubsub::{EthPubSubApi, EthPubSubApiServer}; use ethereum_types::{H160, H256}; diff --git a/template/node/src/rpc.rs b/template/node/src/rpc.rs index 3ea0d6642..2d4b2504e 100644 --- a/template/node/src/rpc.rs +++ b/template/node/src/rpc.rs @@ -70,7 +70,7 @@ pub fn create_full( use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use fc_rpc::{ EthApi, EthApiServer, NetApi, NetApiServer, EthPubSubApi, EthPubSubApiServer, - EthDevSigner, EthSigner, + Web3Api, Web3ApiServer, EthDevSigner, EthSigner, }; let mut io = jsonrpc_core::IoHandler::default(); @@ -111,6 +111,13 @@ pub fn create_full( client.clone(), )) ); + + io.extend_with( + Web3ApiServer::to_delegate(Web3Api::new( + client.clone(), + )) + ); + io.extend_with( EthPubSubApiServer::to_delegate(EthPubSubApi::new( pool.clone(), diff --git a/ts-tests/tests/test-web3api.ts b/ts-tests/tests/test-web3api.ts new file mode 100644 index 000000000..8e6d712d8 --- /dev/null +++ b/ts-tests/tests/test-web3api.ts @@ -0,0 +1,18 @@ +import { expect } from "chai"; +import { step } from "mocha-steps"; +import { describeWithFrontier, customRequest } from "./util"; + +describeWithFrontier("Frontier RPC (Web3Api)", `simple-specs.json`, (context) => { + + step("should get client version", async function () { + const version = await context.web3.eth.getNodeInfo(); + expect(version).to.be.equal("node-frontier-template/v1.1/fc-rpc-0.1.0"); + }); + + step("should remote sha3", async function () { + const data = context.web3.utils.stringToHex("hello"); + const hash = await customRequest(context.web3, "web3_sha3", [data]); + const local_hash = context.web3.utils.sha3("hello"); + expect(hash.result).to.be.equal(local_hash); + }); +});