From 83eec603fd0fa5ae4d6f71cb9d525e3733b7d17e Mon Sep 17 00:00:00 2001 From: tgmichel Date: Tue, 29 Sep 2020 15:22:46 +0200 Subject: [PATCH] Add checks before submit in send_raw_transaction --- rpc/Cargo.toml | 1 + rpc/src/eth.rs | 60 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 5b3c223ed4..837670b7e4 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -20,6 +20,7 @@ sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "rococo- sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } sp-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } +sc-transaction-graph = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } sp-storage = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" } diff --git a/rpc/src/eth.rs b/rpc/src/eth.rs index 040822dae9..0740538efa 100644 --- a/rpc/src/eth.rs +++ b/rpc/src/eth.rs @@ -24,6 +24,7 @@ use sp_runtime::traits::{Block as BlockT, Header as _, UniqueSaturatedInto, Zero use sp_runtime::transaction_validity::TransactionSource; use sp_api::{ProvideRuntimeApi, BlockId}; use sp_transaction_pool::TransactionPool; +use sc_transaction_graph::{Pool, ChainApi}; use sc_client_api::backend::{StorageProvider, Backend, StateBackend, AuxStore}; use sha3::{Keccak256, Digest}; use sp_runtime::traits::BlakeTwo256; @@ -38,22 +39,24 @@ use crate::internal_err; pub use frontier_rpc_core::{EthApiServer, NetApiServer}; -pub struct EthApi { +pub struct EthApi { pool: Arc

, + graph_pool: Arc>, client: Arc, convert_transaction: CT, is_authority: bool, _marker: PhantomData<(B, BE)>, } -impl EthApi { +impl EthApi { pub fn new( client: Arc, + graph_pool: Arc>, pool: Arc

, convert_transaction: CT, is_authority: bool ) -> Self { - Self { client, pool, convert_transaction, is_authority, _marker: PhantomData } + Self { client, pool, graph_pool, convert_transaction, is_authority, _marker: PhantomData } } } @@ -168,7 +171,7 @@ fn transaction_build( } } -impl EthApi where +impl EthApi where C: ProvideRuntimeApi + StorageProvider + AuxStore, C: HeaderBackend + HeaderMetadata + 'static, C::Api: EthereumRuntimeRPCApi, @@ -177,6 +180,7 @@ impl EthApi where B: BlockT + Send + Sync + 'static, C: Send + Sync + 'static, P: TransactionPool + Send + Sync + 'static, + A: ChainApi + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, { fn native_block_id(&self, number: Option) -> Result>> { @@ -237,7 +241,7 @@ impl EthApi where } } -impl EthApiT for EthApi where +impl EthApiT for EthApi where C: ProvideRuntimeApi + StorageProvider + AuxStore, C: HeaderBackend + HeaderMetadata + 'static, C::Api: EthereumRuntimeRPCApi, @@ -246,6 +250,7 @@ impl EthApiT for EthApi where B: BlockT + Send + Sync + 'static, C: Send + Sync + 'static, P: TransactionPool + Send + Sync + 'static, + A: ChainApi + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, { fn protocol_version(&self) -> Result { @@ -476,21 +481,38 @@ impl EthApiT for EthApi where future::result(Err(internal_err("decode transaction failed"))) ), }; - let transaction_hash = H256::from_slice( - Keccak256::digest(&rlp::encode(&transaction)).as_slice() - ); - let hash = self.client.info().best_hash; - Box::new( - self.pool - .submit_one( - &BlockId::hash(hash), - TransactionSource::Local, - self.convert_transaction.convert_transaction(transaction), + // pre-submit checks + let uxt = self.convert_transaction.convert_transaction(transaction.clone()); + let (uxt_hash, _bytes) = self.graph_pool.validated_pool().api().hash_and_length(&uxt); + let check_is_known = self.graph_pool.validated_pool().check_is_known(&uxt_hash,false); + + match check_is_known { + Ok(_) => { + let hash = self.client.info().best_hash; + let transaction_hash = H256::from_slice( + Keccak256::digest(&rlp::encode(&transaction)).as_slice() + ); + Box::new( + self.pool + .submit_one( + &BlockId::hash(hash), + TransactionSource::Local, + uxt, + ) + .compat() + .map(move |_| transaction_hash) + .map_err(|err| internal_err(format!("submit transaction to pool failed: {:?}", err))) ) - .compat() - .map(move |_| transaction_hash) - .map_err(|err| internal_err(format!("submit transaction to pool failed: {:?}", err))) - ) + }, + _ => { + // Transaction is already imported or in the ban list + Box::new( + futures::future::err::<_, jsonrpc_core::types::error::Error>( + internal_err(format!("{:?}",check_is_known)) + ).compat() + ) + } + } } fn call(&self, request: CallRequest, _: Option) -> Result {