parent
							
								
									90a7ca9d10
								
							
						
					
					
						commit
						944bf6a59e
					
				
							
								
								
									
										5
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -729,6 +729,7 @@ dependencies = [
 | 
			
		||||
 "ethkey 0.3.0",
 | 
			
		||||
 "evm 0.1.0",
 | 
			
		||||
 "fetch 0.1.0",
 | 
			
		||||
 "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
 | 
			
		||||
 "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -876,6 +877,7 @@ dependencies = [
 | 
			
		||||
 "ethcore-blockchain 0.1.0",
 | 
			
		||||
 "ethcore-db 0.1.0",
 | 
			
		||||
 "ethcore-io 1.12.0",
 | 
			
		||||
 "ethcore-miner 1.12.0",
 | 
			
		||||
 "ethcore-network 1.12.0",
 | 
			
		||||
 "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "failsafe 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -950,6 +952,9 @@ dependencies = [
 | 
			
		||||
 "price-info 1.12.0",
 | 
			
		||||
 "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "transaction-pool 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ ethereum-types = "0.4"
 | 
			
		||||
ethjson = { path = "../json" }
 | 
			
		||||
ethkey = { path = "../accounts/ethkey" }
 | 
			
		||||
evm = { path = "evm" }
 | 
			
		||||
futures = "0.1"
 | 
			
		||||
hash-db = "0.11.0"
 | 
			
		||||
heapsize = "0.4"
 | 
			
		||||
itertools = "0.5"
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ memory-db = "0.11.0"
 | 
			
		||||
trie-db = "0.11.0"
 | 
			
		||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
 | 
			
		||||
ethcore-network = { path = "../../util/network" }
 | 
			
		||||
ethcore-miner = { path = "../../miner" }
 | 
			
		||||
ethcore-io = { path = "../../util/io" }
 | 
			
		||||
hash-db = "0.11.0"
 | 
			
		||||
heapsize = "0.4"
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,7 @@ extern crate ethcore_io as io;
 | 
			
		||||
extern crate ethcore_network as network;
 | 
			
		||||
extern crate parity_bytes as bytes;
 | 
			
		||||
extern crate ethereum_types;
 | 
			
		||||
extern crate ethcore_miner as miner;
 | 
			
		||||
extern crate ethcore;
 | 
			
		||||
extern crate hash_db;
 | 
			
		||||
extern crate heapsize;
 | 
			
		||||
 | 
			
		||||
@ -24,12 +24,15 @@
 | 
			
		||||
//! address-wise manner.
 | 
			
		||||
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
use std::collections::{BTreeMap, HashMap};
 | 
			
		||||
use std::collections::hash_map::Entry;
 | 
			
		||||
 | 
			
		||||
use common_types::transaction::{self, Condition, PendingTransaction, SignedTransaction};
 | 
			
		||||
use ethereum_types::{H256, U256, Address};
 | 
			
		||||
use fastmap::H256FastMap;
 | 
			
		||||
use futures::sync::mpsc;
 | 
			
		||||
use miner::pool::TxStatus;
 | 
			
		||||
 | 
			
		||||
// Knowledge of an account's current nonce.
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
			
		||||
@ -134,6 +137,7 @@ pub struct TransactionQueue {
 | 
			
		||||
	by_account: HashMap<Address, AccountTransactions>,
 | 
			
		||||
	by_hash: H256FastMap<PendingTransaction>,
 | 
			
		||||
	listeners: Vec<Listener>,
 | 
			
		||||
	tx_statuses_listeners: Vec<mpsc::UnboundedSender<Arc<Vec<(H256, TxStatus)>>>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for TransactionQueue {
 | 
			
		||||
@ -231,7 +235,7 @@ impl TransactionQueue {
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		self.by_hash.insert(hash, tx);
 | 
			
		||||
		self.notify(&promoted);
 | 
			
		||||
		self.notify(&promoted, TxStatus::Added);
 | 
			
		||||
		Ok(res)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -343,6 +347,8 @@ impl TransactionQueue {
 | 
			
		||||
		trace!(target: "txqueue", "Culled {} old transactions from sender {} (nonce={})",
 | 
			
		||||
			removed_hashes.len(), address, cur_nonce);
 | 
			
		||||
 | 
			
		||||
		self.notify(&removed_hashes, TxStatus::Culled);
 | 
			
		||||
 | 
			
		||||
		for hash in removed_hashes {
 | 
			
		||||
			self.by_hash.remove(&hash);
 | 
			
		||||
		}
 | 
			
		||||
@ -358,11 +364,26 @@ impl TransactionQueue {
 | 
			
		||||
		self.listeners.push(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Add a transaction queue listener.
 | 
			
		||||
	pub fn tx_statuses_receiver(&mut self) -> mpsc::UnboundedReceiver<Arc<Vec<(H256, TxStatus)>>> {
 | 
			
		||||
		let (sender, receiver) = mpsc::unbounded();
 | 
			
		||||
		self.tx_statuses_listeners.push(sender);
 | 
			
		||||
		receiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Notifies all listeners about new pending transaction.
 | 
			
		||||
	fn notify(&self, hashes: &[H256]) {
 | 
			
		||||
	fn notify(&mut self, hashes: &[H256], status: TxStatus) {
 | 
			
		||||
		for listener in &self.listeners {
 | 
			
		||||
			listener(hashes)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let to_send: Arc<Vec<(H256, TxStatus)>> = Arc::new(
 | 
			
		||||
			hashes
 | 
			
		||||
				.into_iter()
 | 
			
		||||
				.map(|hash| (hash.clone(), status)).collect()
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		self.tx_statuses_listeners.retain(| listener| listener.unbounded_send(to_send.clone()).is_ok());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -74,6 +74,7 @@ extern crate ethcore_miner;
 | 
			
		||||
extern crate ethereum_types;
 | 
			
		||||
extern crate ethjson;
 | 
			
		||||
extern crate ethkey;
 | 
			
		||||
extern crate futures;
 | 
			
		||||
extern crate hash_db;
 | 
			
		||||
extern crate heapsize;
 | 
			
		||||
extern crate itertools;
 | 
			
		||||
 | 
			
		||||
@ -24,11 +24,12 @@ use bytes::Bytes;
 | 
			
		||||
use call_contract::CallContract;
 | 
			
		||||
use ethcore_miner::gas_pricer::GasPricer;
 | 
			
		||||
use ethcore_miner::local_accounts::LocalAccounts;
 | 
			
		||||
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy};
 | 
			
		||||
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy, TxStatus};
 | 
			
		||||
use ethcore_miner::service_transaction_checker::ServiceTransactionChecker;
 | 
			
		||||
#[cfg(feature = "work-notify")]
 | 
			
		||||
use ethcore_miner::work_notify::NotifyWork;
 | 
			
		||||
use ethereum_types::{H256, U256, Address};
 | 
			
		||||
use futures::sync::mpsc;
 | 
			
		||||
use io::IoChannel;
 | 
			
		||||
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
 | 
			
		||||
use miner;
 | 
			
		||||
@ -263,6 +264,13 @@ impl Miner {
 | 
			
		||||
		self.transaction_queue.add_listener(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Set a callback to be notified
 | 
			
		||||
	pub fn tx_pool_receiver(&self) -> mpsc::UnboundedReceiver<Arc<Vec<(H256, TxStatus)>>> {
 | 
			
		||||
		let (sender, receiver) = mpsc::unbounded();
 | 
			
		||||
		self.transaction_queue.add_tx_pool_listener(sender);
 | 
			
		||||
		receiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Creates new instance of miner Arc.
 | 
			
		||||
	pub fn new<A: LocalAccounts + 'static>(
 | 
			
		||||
		options: MinerOptions,
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,9 @@ parity-runtime = { path = "../util/runtime" }
 | 
			
		||||
parking_lot = "0.7"
 | 
			
		||||
price-info = { path = "./price-info", optional = true }
 | 
			
		||||
rlp = { version = "0.3.0", features = ["ethereum"] }
 | 
			
		||||
serde = "1.0"
 | 
			
		||||
serde_derive = "1.0"
 | 
			
		||||
serde_json = "1.0"
 | 
			
		||||
trace-time = "0.1"
 | 
			
		||||
transaction-pool = "2.0"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@ extern crate parking_lot;
 | 
			
		||||
extern crate price_info;
 | 
			
		||||
extern crate rlp;
 | 
			
		||||
extern crate transaction_pool as txpool;
 | 
			
		||||
extern crate serde;
 | 
			
		||||
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate ethabi_contract;
 | 
			
		||||
@ -44,6 +45,8 @@ extern crate error_chain;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate log;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate serde_derive;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate trace_time;
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,11 @@ use std::fmt;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
use ethereum_types::H256;
 | 
			
		||||
use futures::sync::mpsc;
 | 
			
		||||
use txpool::{self, VerifiedTransaction};
 | 
			
		||||
 | 
			
		||||
use pool::VerifiedTransaction as Transaction;
 | 
			
		||||
use pool::TxStatus;
 | 
			
		||||
 | 
			
		||||
type Listener = Box<Fn(&[H256]) + Send + Sync>;
 | 
			
		||||
 | 
			
		||||
@ -116,6 +118,65 @@ impl txpool::Listener<Transaction> for Logger {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Transactions pool notifier
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct TransactionsPoolNotifier {
 | 
			
		||||
	listeners: Vec<mpsc::UnboundedSender<Arc<Vec<(H256, TxStatus)>>>>,
 | 
			
		||||
	tx_statuses: Vec<(H256, TxStatus)>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TransactionsPoolNotifier {
 | 
			
		||||
	/// Add new listener to receive notifications.
 | 
			
		||||
	pub fn add(&mut self, f: mpsc::UnboundedSender<Arc<Vec<(H256, TxStatus)>>>) {
 | 
			
		||||
		self.listeners.push(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Notify listeners about all currently transactions.
 | 
			
		||||
	pub fn notify(&mut self) {
 | 
			
		||||
		if self.tx_statuses.is_empty() {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let to_send = Arc::new(std::mem::replace(&mut self.tx_statuses, Vec::new()));
 | 
			
		||||
		self.listeners
 | 
			
		||||
			.retain(|listener| listener.unbounded_send(to_send.clone()).is_ok());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for TransactionsPoolNotifier {
 | 
			
		||||
	fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
		fmt.debug_struct("TransactionsPoolNotifier")
 | 
			
		||||
			.field("listeners", &self.listeners.len())
 | 
			
		||||
			.finish()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl txpool::Listener<Transaction> for TransactionsPoolNotifier {
 | 
			
		||||
	fn added(&mut self, tx: &Arc<Transaction>, _old: Option<&Arc<Transaction>>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Added));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn rejected<H: fmt::Debug + fmt::LowerHex>(&mut self, tx: &Arc<Transaction>, _reason: &txpool::Error<H>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Rejected));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn dropped(&mut self, tx: &Arc<Transaction>, _new: Option<&Transaction>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Dropped));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn invalid(&mut self, tx: &Arc<Transaction>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Invalid));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn canceled(&mut self, tx: &Arc<Transaction>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Canceled));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn culled(&mut self, tx: &Arc<Transaction>) {
 | 
			
		||||
		self.tx_statuses.push((tx.hash.clone(), TxStatus::Culled));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
	use super::*;
 | 
			
		||||
 | 
			
		||||
@ -199,3 +199,21 @@ impl ScoredTransaction for VerifiedTransaction {
 | 
			
		||||
		self.transaction.nonce
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Pool transactions status
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
#[serde(rename_all = "camelCase")]
 | 
			
		||||
pub enum TxStatus {
 | 
			
		||||
	/// Added transaction
 | 
			
		||||
	Added,
 | 
			
		||||
	/// Rejected transaction
 | 
			
		||||
	Rejected,
 | 
			
		||||
	/// Dropped transaction
 | 
			
		||||
	Dropped,
 | 
			
		||||
	/// Invalid transaction
 | 
			
		||||
	Invalid,
 | 
			
		||||
	/// Canceled transaction
 | 
			
		||||
	Canceled,
 | 
			
		||||
	/// Culled transaction
 | 
			
		||||
	Culled,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,17 +22,18 @@ use std::sync::atomic::{self, AtomicUsize};
 | 
			
		||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
 | 
			
		||||
 | 
			
		||||
use ethereum_types::{H256, U256, Address};
 | 
			
		||||
use futures::sync::mpsc;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use txpool::{self, Verifier};
 | 
			
		||||
use types::transaction;
 | 
			
		||||
 | 
			
		||||
use pool::{
 | 
			
		||||
	self, replace, scoring, verifier, client, ready, listener,
 | 
			
		||||
	PrioritizationStrategy, PendingOrdering, PendingSettings,
 | 
			
		||||
	PrioritizationStrategy, PendingOrdering, PendingSettings, TxStatus
 | 
			
		||||
};
 | 
			
		||||
use pool::local_transactions::LocalTransactionsList;
 | 
			
		||||
 | 
			
		||||
type Listener = (LocalTransactionsList, (listener::Notifier, listener::Logger));
 | 
			
		||||
type Listener = (LocalTransactionsList, (listener::Notifier, (listener::Logger, listener::TransactionsPoolNotifier)));
 | 
			
		||||
type Pool = txpool::Pool<pool::VerifiedTransaction, scoring::NonceAndGasPrice, Listener>;
 | 
			
		||||
 | 
			
		||||
/// Max cache time in milliseconds for pending transactions.
 | 
			
		||||
@ -304,6 +305,8 @@ impl TransactionQueue {
 | 
			
		||||
		// Notify about imported transactions.
 | 
			
		||||
		(self.pool.write().listener_mut().1).0.notify();
 | 
			
		||||
 | 
			
		||||
		((self.pool.write().listener_mut().1).1).1.notify();
 | 
			
		||||
 | 
			
		||||
		if results.iter().any(|r| r.is_ok()) {
 | 
			
		||||
			self.cached_pending.write().clear();
 | 
			
		||||
		}
 | 
			
		||||
@ -574,6 +577,12 @@ impl TransactionQueue {
 | 
			
		||||
		(pool.listener_mut().1).0.add(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Add a listener to be notified about all transactions the pool
 | 
			
		||||
	pub fn add_tx_pool_listener(&self, f: mpsc::UnboundedSender<Arc<Vec<(H256, TxStatus)>>>) {
 | 
			
		||||
		let mut pool = self.pool.write();
 | 
			
		||||
		((pool.listener_mut().1).1).1.add(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Check if pending set is cached.
 | 
			
		||||
	#[cfg(test)]
 | 
			
		||||
	pub fn is_pending_cached(&self) -> bool {
 | 
			
		||||
 | 
			
		||||
@ -498,7 +498,7 @@ usage! {
 | 
			
		||||
			"--jsonrpc-interface=[IP]",
 | 
			
		||||
			"Specify the hostname portion of the HTTP JSON-RPC API server, IP should be an interface's IP address, or all (all interfaces) or local.",
 | 
			
		||||
 | 
			
		||||
			ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,shh,shh_pubsub", or |c: &Config| c.rpc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,shh,shh_pubsub,parity_transactions_pool", or |c: &Config| c.rpc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			"--jsonrpc-apis=[APIS]",
 | 
			
		||||
			"Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore, shh, shh_pubsub. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc, shh, shh_pubsub",
 | 
			
		||||
 | 
			
		||||
@ -539,7 +539,7 @@ usage! {
 | 
			
		||||
			"--ws-interface=[IP]",
 | 
			
		||||
			"Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local.",
 | 
			
		||||
 | 
			
		||||
			ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,shh,shh_pubsub", or |c: &Config| c.websockets.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,shh,shh_pubsub,parity_transactions_pool", or |c: &Config| c.websockets.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			"--ws-apis=[APIS]",
 | 
			
		||||
			"Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore, shh, shh_pubsub. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc, shh, shh_pubsub",
 | 
			
		||||
 | 
			
		||||
@ -564,7 +564,7 @@ usage! {
 | 
			
		||||
			"--ipc-path=[PATH]",
 | 
			
		||||
			"Specify custom path for JSON-RPC over IPC service.",
 | 
			
		||||
 | 
			
		||||
			ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,shh,shh_pubsub", or |c: &Config| c.ipc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,shh,shh_pubsub,parity_transactions_pool", or |c: &Config| c.ipc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")),
 | 
			
		||||
			"--ipc-apis=[APIS]",
 | 
			
		||||
			"Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore, shh, shh_pubsub. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc, shh, shh_pubsub",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ use miner::external::ExternalMiner;
 | 
			
		||||
use parity_rpc::dispatch::{FullDispatcher, LightDispatcher};
 | 
			
		||||
use parity_rpc::informant::{ActivityNotifier, ClientNotifier};
 | 
			
		||||
use parity_rpc::{Host, Metadata, NetworkSettings};
 | 
			
		||||
use parity_rpc::v1::traits::TransactionsPool;
 | 
			
		||||
use parity_runtime::Executor;
 | 
			
		||||
use parking_lot::{Mutex, RwLock};
 | 
			
		||||
use sync::{LightSync, ManageNetwork, SyncProvider};
 | 
			
		||||
@ -82,6 +83,8 @@ pub enum Api {
 | 
			
		||||
	/// Geth-compatible (best-effort) debug API (Potentially UNSAFE)
 | 
			
		||||
	/// NOTE We don't aim to support all methods, only the ones that are useful.
 | 
			
		||||
	Debug,
 | 
			
		||||
	/// Parity Transactions pool PubSub
 | 
			
		||||
	ParityTransactionsPool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromStr for Api {
 | 
			
		||||
@ -108,6 +111,7 @@ impl FromStr for Api {
 | 
			
		||||
			"signer" => Ok(Signer),
 | 
			
		||||
			"traces" => Ok(Traces),
 | 
			
		||||
			"web3" => Ok(Web3),
 | 
			
		||||
			"parity_transactions_pool" => Ok(ParityTransactionsPool),
 | 
			
		||||
			api => Err(format!("Unknown api: {}", api)),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -191,6 +195,7 @@ fn to_modules(apis: &HashSet<Api>) -> BTreeMap<String, String> {
 | 
			
		||||
			Api::Web3 => ("web3", "1.0"),
 | 
			
		||||
			Api::Whisper => ("shh", "1.0"),
 | 
			
		||||
			Api::WhisperPubSub => ("shh_pubsub", "1.0"),
 | 
			
		||||
			Api::ParityTransactionsPool => ("parity_transactions_pool", "1.0"),
 | 
			
		||||
		};
 | 
			
		||||
		modules.insert(name.into(), version.into());
 | 
			
		||||
	}
 | 
			
		||||
@ -352,6 +357,13 @@ impl FullDependencies {
 | 
			
		||||
						handler.extend_with(client.to_delegate());
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				Api::ParityTransactionsPool => {
 | 
			
		||||
					if !for_generic_pubsub {
 | 
			
		||||
						let receiver = self.miner.tx_pool_receiver();
 | 
			
		||||
						let client = TransactionsPoolClient::new(self.executor.clone(), receiver);
 | 
			
		||||
						handler.extend_with(TransactionsPoolClient::to_delegate(client));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				Api::Personal => {
 | 
			
		||||
					#[cfg(feature = "accounts")]
 | 
			
		||||
					handler.extend_with(
 | 
			
		||||
@ -603,6 +615,13 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
 | 
			
		||||
						}));
 | 
			
		||||
					handler.extend_with(EthPubSub::to_delegate(client));
 | 
			
		||||
				}
 | 
			
		||||
				Api::ParityTransactionsPool => {
 | 
			
		||||
					if !for_generic_pubsub {
 | 
			
		||||
						let receiver = self.transaction_queue.write().tx_statuses_receiver();
 | 
			
		||||
						let client = TransactionsPoolClient::new(self.executor.clone(), receiver);
 | 
			
		||||
						handler.extend_with(TransactionsPoolClient::to_delegate(client));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				Api::Personal => {
 | 
			
		||||
					#[cfg(feature = "accounts")]
 | 
			
		||||
					handler.extend_with(
 | 
			
		||||
@ -744,12 +763,14 @@ impl ApiSet {
 | 
			
		||||
			ApiSet::UnsafeContext => {
 | 
			
		||||
				public_list.insert(Api::Traces);
 | 
			
		||||
				public_list.insert(Api::ParityPubSub);
 | 
			
		||||
				public_list.insert(Api::ParityTransactionsPool);
 | 
			
		||||
				public_list
 | 
			
		||||
			}
 | 
			
		||||
			ApiSet::IpcContext => {
 | 
			
		||||
				public_list.insert(Api::Traces);
 | 
			
		||||
				public_list.insert(Api::ParityPubSub);
 | 
			
		||||
				public_list.insert(Api::ParityAccounts);
 | 
			
		||||
				public_list.insert(Api::ParityTransactionsPool);
 | 
			
		||||
				public_list
 | 
			
		||||
			}
 | 
			
		||||
			ApiSet::All => {
 | 
			
		||||
@ -761,6 +782,7 @@ impl ApiSet {
 | 
			
		||||
				public_list.insert(Api::Signer);
 | 
			
		||||
				public_list.insert(Api::Personal);
 | 
			
		||||
				public_list.insert(Api::SecretStore);
 | 
			
		||||
				public_list.insert(Api::ParityTransactionsPool);
 | 
			
		||||
				public_list
 | 
			
		||||
			}
 | 
			
		||||
			ApiSet::PubSub => [
 | 
			
		||||
@ -769,6 +791,7 @@ impl ApiSet {
 | 
			
		||||
				Api::ParityAccounts,
 | 
			
		||||
				Api::ParitySet,
 | 
			
		||||
				Api::Traces,
 | 
			
		||||
				Api::ParityTransactionsPool,
 | 
			
		||||
			]
 | 
			
		||||
				.into_iter()
 | 
			
		||||
				.cloned()
 | 
			
		||||
@ -799,6 +822,7 @@ mod test {
 | 
			
		||||
		assert_eq!(Api::Private, "private".parse().unwrap());
 | 
			
		||||
		assert_eq!(Api::Whisper, "shh".parse().unwrap());
 | 
			
		||||
		assert_eq!(Api::WhisperPubSub, "shh_pubsub".parse().unwrap());
 | 
			
		||||
		assert_eq!(Api::ParityTransactionsPool, "parity_transactions_pool".parse().unwrap());
 | 
			
		||||
		assert!("rp".parse::<Api>().is_err());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -830,6 +854,7 @@ mod test {
 | 
			
		||||
			Api::Whisper,
 | 
			
		||||
			Api::WhisperPubSub,
 | 
			
		||||
			Api::Private,
 | 
			
		||||
			Api::ParityTransactionsPool,
 | 
			
		||||
		].into_iter()
 | 
			
		||||
		.collect();
 | 
			
		||||
		assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
 | 
			
		||||
@ -850,6 +875,7 @@ mod test {
 | 
			
		||||
			Api::Whisper,
 | 
			
		||||
			Api::WhisperPubSub,
 | 
			
		||||
			Api::Private,
 | 
			
		||||
			Api::ParityTransactionsPool,
 | 
			
		||||
			// semi-safe
 | 
			
		||||
			Api::ParityAccounts,
 | 
			
		||||
		].into_iter()
 | 
			
		||||
@ -880,6 +906,7 @@ mod test {
 | 
			
		||||
					Api::Personal,
 | 
			
		||||
					Api::Private,
 | 
			
		||||
					Api::Debug,
 | 
			
		||||
					Api::ParityTransactionsPool,
 | 
			
		||||
				].into_iter()
 | 
			
		||||
				.collect()
 | 
			
		||||
			)
 | 
			
		||||
@ -908,6 +935,7 @@ mod test {
 | 
			
		||||
					Api::Signer,
 | 
			
		||||
					Api::Private,
 | 
			
		||||
					Api::Debug,
 | 
			
		||||
					Api::ParityTransactionsPool,
 | 
			
		||||
				].into_iter()
 | 
			
		||||
				.collect()
 | 
			
		||||
			)
 | 
			
		||||
@ -931,6 +959,7 @@ mod test {
 | 
			
		||||
					Api::Whisper,
 | 
			
		||||
					Api::WhisperPubSub,
 | 
			
		||||
					Api::Private,
 | 
			
		||||
					Api::ParityTransactionsPool,
 | 
			
		||||
				].into_iter()
 | 
			
		||||
				.collect()
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,7 @@ mod signer;
 | 
			
		||||
mod signing;
 | 
			
		||||
mod signing_unsafe;
 | 
			
		||||
mod traces;
 | 
			
		||||
mod transactions_pool;
 | 
			
		||||
mod web3;
 | 
			
		||||
 | 
			
		||||
pub mod light;
 | 
			
		||||
@ -44,6 +45,7 @@ pub use self::debug::DebugClient;
 | 
			
		||||
pub use self::eth::{EthClient, EthClientOptions};
 | 
			
		||||
pub use self::eth_filter::EthFilterClient;
 | 
			
		||||
pub use self::eth_pubsub::EthPubSubClient;
 | 
			
		||||
pub use self::transactions_pool::TransactionsPoolClient;
 | 
			
		||||
pub use self::net::NetClient;
 | 
			
		||||
pub use self::parity::ParityClient;
 | 
			
		||||
#[cfg(any(test, feature = "accounts"))]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										101
									
								
								rpc/src/v1/impls/transactions_pool.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								rpc/src/v1/impls/transactions_pool.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
use std::sync::{Arc, Weak};
 | 
			
		||||
 | 
			
		||||
use jsonrpc_core::Result;
 | 
			
		||||
use jsonrpc_core::futures::Future;
 | 
			
		||||
use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}};
 | 
			
		||||
 | 
			
		||||
use v1::helpers::Subscribers;
 | 
			
		||||
use v1::metadata::Metadata;
 | 
			
		||||
use v1::traits::TransactionsPool;
 | 
			
		||||
 | 
			
		||||
use miner::pool::TxStatus;
 | 
			
		||||
use parity_runtime::Executor;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use ethereum_types::H256;
 | 
			
		||||
use futures::{Stream, sync::mpsc};
 | 
			
		||||
 | 
			
		||||
type Client = Sink<(H256, TxStatus)>;
 | 
			
		||||
 | 
			
		||||
/// Transactions pool PubSub implementation.
 | 
			
		||||
pub struct TransactionsPoolClient {
 | 
			
		||||
	handler: Arc<TransactionsNotificationHandler>,
 | 
			
		||||
	transactions_pool_subscribers: Arc<RwLock<Subscribers<Client>>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TransactionsPoolClient {
 | 
			
		||||
	/// Creates new `TransactionsPoolClient`.
 | 
			
		||||
	pub fn new(executor: Executor, pool_receiver: mpsc::UnboundedReceiver<Arc<Vec<(H256, TxStatus)>>>) -> Self {
 | 
			
		||||
		let transactions_pool_subscribers = Arc::new(RwLock::new(Subscribers::default()));
 | 
			
		||||
		let handler = Arc::new(
 | 
			
		||||
			TransactionsNotificationHandler::new(
 | 
			
		||||
				executor.clone(),
 | 
			
		||||
				transactions_pool_subscribers.clone(),
 | 
			
		||||
			)
 | 
			
		||||
		);
 | 
			
		||||
		let handler2 = Arc::downgrade(&handler);
 | 
			
		||||
 | 
			
		||||
		executor.spawn(pool_receiver
 | 
			
		||||
			.for_each(move |tx_status| {
 | 
			
		||||
				if let Some(handler2) = handler2.upgrade() {
 | 
			
		||||
					handler2.notify_transaction(tx_status);
 | 
			
		||||
				}
 | 
			
		||||
				Ok(())
 | 
			
		||||
			})
 | 
			
		||||
			.map_err(|e| warn!("Key server listener error: {:?}", e))
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		TransactionsPoolClient {
 | 
			
		||||
			handler,
 | 
			
		||||
			transactions_pool_subscribers,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Returns a chain notification handler.
 | 
			
		||||
	pub fn handler(&self) -> Weak<TransactionsNotificationHandler> {
 | 
			
		||||
		Arc::downgrade(&self.handler)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Transactions pool PubSub Notification handler.
 | 
			
		||||
pub struct TransactionsNotificationHandler {
 | 
			
		||||
	executor: Executor,
 | 
			
		||||
	transactions_pool_subscribers: Arc<RwLock<Subscribers<Client>>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TransactionsNotificationHandler {
 | 
			
		||||
	fn new(executor: Executor, transactions_pool_subscribers: Arc<RwLock<Subscribers<Client>>>) -> Self {
 | 
			
		||||
		TransactionsNotificationHandler {
 | 
			
		||||
			executor,
 | 
			
		||||
			transactions_pool_subscribers,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn notify(executor: &Executor, subscriber: &Client, result: (H256, TxStatus)) {
 | 
			
		||||
		executor.spawn(subscriber
 | 
			
		||||
			.notify(Ok(result))
 | 
			
		||||
			.map(|_| ())
 | 
			
		||||
			.map_err(|e| warn!(target: "rpc", "Unable to send notification: {}", e))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub fn notify_transaction(&self, tx_statuses: Arc<Vec<(H256, TxStatus)>>) {
 | 
			
		||||
		for subscriber in self.transactions_pool_subscribers.read().values() {
 | 
			
		||||
			for tx_status in tx_statuses.to_vec() {
 | 
			
		||||
				Self::notify(&self.executor, subscriber, tx_status.clone());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TransactionsPool for TransactionsPoolClient {
 | 
			
		||||
	type Metadata = Metadata;
 | 
			
		||||
 | 
			
		||||
	fn subscribe(&self, _meta: Metadata, subscriber: Subscriber<(H256, TxStatus)>) {
 | 
			
		||||
		self.transactions_pool_subscribers.write().push(subscriber);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn unsubscribe(&self, _meta: Option<Metadata>, id: SubscriptionId) -> Result<bool> {
 | 
			
		||||
		let res = self.transactions_pool_subscribers.write().remove(&id).is_some();
 | 
			
		||||
		Ok(res)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -32,6 +32,7 @@ pub mod rpc;
 | 
			
		||||
pub mod secretstore;
 | 
			
		||||
pub mod signer;
 | 
			
		||||
pub mod traces;
 | 
			
		||||
pub mod transactions_pool;
 | 
			
		||||
pub mod web3;
 | 
			
		||||
 | 
			
		||||
pub use self::debug::Debug;
 | 
			
		||||
@ -50,4 +51,5 @@ pub use self::rpc::Rpc;
 | 
			
		||||
pub use self::secretstore::SecretStore;
 | 
			
		||||
pub use self::signer::Signer;
 | 
			
		||||
pub use self::traces::Traces;
 | 
			
		||||
pub use self::transactions_pool::TransactionsPool;
 | 
			
		||||
pub use self::web3::Web3;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								rpc/src/v1/traits/transactions_pool.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								rpc/src/v1/traits/transactions_pool.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
//! Transactions pool PUB-SUB rpc interface.
 | 
			
		||||
 | 
			
		||||
use jsonrpc_core::Result;
 | 
			
		||||
use jsonrpc_pubsub::{typed, SubscriptionId};
 | 
			
		||||
use jsonrpc_derive::rpc;
 | 
			
		||||
use miner::pool::TxStatus;
 | 
			
		||||
 | 
			
		||||
use ethereum_types::H256;
 | 
			
		||||
 | 
			
		||||
/// Transactions Pool PUB-SUB rpc interface.
 | 
			
		||||
#[rpc]
 | 
			
		||||
pub trait TransactionsPool {
 | 
			
		||||
	/// Pub/Sub Metadata
 | 
			
		||||
	type Metadata;
 | 
			
		||||
 | 
			
		||||
	/// Subscribe to Transactions Pool subscription.
 | 
			
		||||
	#[pubsub(subscription = "parity_watchTransactionsPool", subscribe, name = "parity_watchTransactionsPool")]
 | 
			
		||||
	fn subscribe(&self, Self::Metadata, typed::Subscriber<(H256, TxStatus)>);
 | 
			
		||||
 | 
			
		||||
	/// Unsubscribe from existing Transactions Pool subscription.
 | 
			
		||||
	#[pubsub(subscription = "parity_watchTransactionsPool", unsubscribe, name = "parity_unwatchTransactionsPool")]
 | 
			
		||||
	fn unsubscribe(&self, Option<Self::Metadata>, SubscriptionId) -> Result<bool>;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user