From 34d28189ea48a8d1605508880dce6a9c73517d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 19 Mar 2017 08:46:51 +0100 Subject: [PATCH] Remove transaction RPC (#4949) --- ethcore/src/miner/miner.rs | 10 ++++++++ ethcore/src/miner/mod.rs | 4 ++++ rpc/src/v1/impls/light/parity_set.rs | 6 ++++- rpc/src/v1/impls/parity_set.rs | 24 +++++++++---------- rpc/src/v1/tests/helpers/miner_service.rs | 4 ++++ rpc/src/v1/tests/mocked/parity_set.rs | 28 +++++++++++++++++++++++ rpc/src/v1/traits/parity_set.rs | 11 ++++++++- 7 files changed, 72 insertions(+), 15 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 5d8d73837..5cbc8f76b 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1018,6 +1018,16 @@ impl MinerService for Miner { } } + fn remove_pending_transaction(&self, chain: &MiningBlockChainClient, hash: &H256) -> Option { + let mut queue = self.transaction_queue.lock(); + let tx = queue.find(hash); + if tx.is_some() { + let fetch_nonce = |a: &Address| chain.latest_nonce(a); + queue.remove_invalid(hash, &fetch_nonce); + } + tx + } + fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option { self.from_pending_block( best_block, diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 403aca760..a9e7a9a5d 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -150,6 +150,10 @@ pub trait MinerService : Send + Sync { /// Query pending transactions for hash. fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option; + /// Removes transaction from the queue. + /// NOTE: The transaction is not removed from pending block if mining. + fn remove_pending_transaction(&self, chain: &MiningBlockChainClient, hash: &H256) -> Option; + /// Get a list of all pending transactions in the queue. fn pending_transactions(&self) -> Vec; diff --git a/rpc/src/v1/impls/light/parity_set.rs b/rpc/src/v1/impls/light/parity_set.rs index 2127db345..40af2f44c 100644 --- a/rpc/src/v1/impls/light/parity_set.rs +++ b/rpc/src/v1/impls/light/parity_set.rs @@ -28,7 +28,7 @@ use util::sha3; use jsonrpc_core::Error; use v1::helpers::errors; use v1::traits::ParitySet; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo}; +use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; /// Parity-specific rpc interface for operations altering the settings. pub struct ParitySetClient { @@ -139,4 +139,8 @@ impl ParitySet for ParitySetClient { fn execute_upgrade(&self) -> Result { Err(errors::light_unimplemented(None)) } + + fn remove_transaction(&self, _hash: H256) -> Result, Error> { + Err(errors::light_unimplemented(None)) + } } diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index 0c844c163..19483635c 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -30,15 +30,10 @@ use updater::{Service as UpdateService}; use jsonrpc_core::Error; use v1::helpers::errors; use v1::traits::ParitySet; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo}; +use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; /// Parity-specific rpc interface for operations altering the settings. -pub struct ParitySetClient where - C: MiningBlockChainClient, - M: MinerService, - U: UpdateService, - F: Fetch, -{ +pub struct ParitySetClient { client: Weak, miner: Weak, updater: Weak, @@ -46,12 +41,7 @@ pub struct ParitySetClient where fetch: F, } -impl ParitySetClient where - C: MiningBlockChainClient, - M: MinerService, - U: UpdateService, - F: Fetch, -{ +impl ParitySetClient { /// Creates new `ParitySetClient` with given `Fetch`. pub fn new(client: &Arc, miner: &Arc, updater: &Arc, net: &Arc, fetch: F) -> Self { ParitySetClient { @@ -181,4 +171,12 @@ impl ParitySet for ParitySetClient where let updater = take_weak!(self.updater); Ok(updater.execute_upgrade()) } + + fn remove_transaction(&self, hash: H256) -> Result, Error> { + let miner = take_weak!(self.miner); + let client = take_weak!(self.client); + let hash = hash.into(); + + Ok(miner.remove_pending_transaction(&*client, &hash).map(Into::into)) + } } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index f84431e6e..4cdfbbd8c 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -221,6 +221,10 @@ impl MinerService for TestMinerService { self.pending_transactions.lock().get(hash).cloned().map(Into::into) } + fn remove_pending_transaction(&self, _chain: &MiningBlockChainClient, hash: &H256) -> Option { + self.pending_transactions.lock().remove(hash).map(Into::into) + } + fn pending_transactions(&self) -> Vec { self.pending_transactions.lock().values().cloned().map(Into::into).collect() } diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 337090499..65d69775a 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -204,3 +204,31 @@ fn rpc_parity_set_hash_content() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_parity_remove_transaction() { + use ethcore::transaction::{Transaction, Action}; + + let miner = miner_service(); + let client = client_service(); + let network = network_service(); + let updater = updater_service(); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + + let tx = Transaction { + nonce: 1.into(), + gas_price: 0x9184e72a000u64.into(), + gas: 0x76c0.into(), + action: Action::Call(5.into()), + value: 0x9184e72au64.into(), + data: vec![] + }; + let signed = tx.fake_sign(2.into()); + let hash = signed.hash(); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""#.to_owned() + &format!("0x{:?}", hash) + r#""], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x0072c69d780cdfbfc02fed5c7d184151f9a166971d045e55e27695aaa5bcb55e","input":"0x","networkId":null,"nonce":"0x1","publicKey":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","r":"0x0","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80808080","s":"0x0","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#; + + miner.pending_transactions.lock().insert(hash, signed); + assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index d5fc066fa..b91b33574 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -19,7 +19,7 @@ use jsonrpc_core::Error; use futures::BoxFuture; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo}; +use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; build_rpc_trait! { /// Parity-specific rpc interface for operations altering the settings. @@ -103,5 +103,14 @@ build_rpc_trait! { /// Execute a release which is ready according to upgrade_ready(). #[rpc(name = "parity_executeUpgrade")] fn execute_upgrade(&self) -> Result; + + /// Removes transaction from transaction queue. + /// Makes sense only for transactions that were not propagated to other peers yet + /// like scheduled transactions or transactions in future. + /// It might also work for some local transactions with to low gas price + /// or excessive gas limit that are not accepted by other peers whp. + /// Returns `true` when transaction was removed, `false` if it was not found. + #[rpc(name = "parity_removeTransaction")] + fn remove_transaction(&self, H256) -> Result, Error>; } }