Merge branch 'master' into tx_queue_rpc
This commit is contained in:
		
						commit
						cc47c80243
					
				
							
								
								
									
										30
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										30
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -15,6 +15,7 @@ dependencies = [ | ||||
|  "fdlimit 0.1.0", | ||||
|  "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| @ -236,8 +237,8 @@ dependencies = [ | ||||
|  "ethcore 0.9.99", | ||||
|  "ethcore-util 0.9.99", | ||||
|  "ethsync 0.9.99", | ||||
|  "jsonrpc-core 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-http-server 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-http-server 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| @ -409,7 +410,7 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "jsonrpc-core" | ||||
| version = "1.2.0" | ||||
| version = "2.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| @ -420,11 +421,11 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "jsonrpc-http-server" | ||||
| version = "2.1.0" | ||||
| version = "3.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-core 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| @ -699,6 +700,17 @@ dependencies = [ | ||||
|  "librocksdb-sys 0.2.1 (git+https://github.com/arkpar/rust-rocksdb.git)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rpassword" | ||||
| version = "0.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rust-crypto" | ||||
| version = "0.2.34" | ||||
| @ -832,6 +844,14 @@ dependencies = [ | ||||
|  "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "termios" | ||||
| version = "0.2.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "time" | ||||
| version = "0.1.34" | ||||
|  | ||||
| @ -21,6 +21,7 @@ fdlimit = { path = "util/fdlimit" } | ||||
| daemonize = "0.2" | ||||
| ethcore-devtools = { path = "devtools" } | ||||
| number_prefix = "0.2" | ||||
| rpassword = "0.1" | ||||
| 
 | ||||
| [features] | ||||
| default = ["rpc"] | ||||
|  | ||||
| @ -320,6 +320,9 @@ impl BlockQueue { | ||||
| 
 | ||||
| 	/// Mark given block and all its children as bad. Stops verification.
 | ||||
| 	pub fn mark_as_bad(&mut self, block_hashes: &[H256]) { | ||||
| 		if block_hashes.is_empty() { | ||||
| 			return; | ||||
| 		} | ||||
| 		let mut verification_lock = self.verification.lock().unwrap(); | ||||
| 		let mut processing = self.processing.write().unwrap(); | ||||
| 
 | ||||
| @ -345,6 +348,9 @@ impl BlockQueue { | ||||
| 
 | ||||
| 	/// Mark given block as processed
 | ||||
| 	pub fn mark_as_good(&mut self, block_hashes: &[H256]) { | ||||
| 		if block_hashes.is_empty() { | ||||
| 			return; | ||||
| 		} | ||||
| 		let mut processing = self.processing.write().unwrap(); | ||||
| 		for hash in block_hashes { | ||||
| 			processing.remove(&hash); | ||||
|  | ||||
| @ -409,9 +409,13 @@ impl<V> Client<V> where V: Verifier { | ||||
| 
 | ||||
| 		{ | ||||
| 			let mut block_queue = self.block_queue.write().unwrap(); | ||||
| 			if !bad_blocks.is_empty() { | ||||
| 				block_queue.mark_as_bad(&bad_blocks); | ||||
| 			} | ||||
| 			if !good_blocks.is_empty() { | ||||
| 				block_queue.mark_as_good(&good_blocks); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		{ | ||||
| 			let block_queue = self.block_queue.read().unwrap(); | ||||
|  | ||||
| @ -17,9 +17,11 @@ | ||||
| pub mod verification; | ||||
| pub mod verifier; | ||||
| mod canon_verifier; | ||||
| #[cfg(test)] | ||||
| mod noop_verifier; | ||||
| 
 | ||||
| pub use self::verification::*; | ||||
| pub use self::verifier::Verifier; | ||||
| pub use self::canon_verifier::CanonVerifier; | ||||
| #[cfg(test)] | ||||
| pub use self::noop_verifier::NoopVerifier; | ||||
|  | ||||
| @ -32,6 +32,7 @@ extern crate fdlimit; | ||||
| extern crate daemonize; | ||||
| extern crate time; | ||||
| extern crate number_prefix; | ||||
| extern crate rpassword; | ||||
| 
 | ||||
| #[cfg(feature = "rpc")] | ||||
| extern crate ethcore_rpc as rpc; | ||||
| @ -43,7 +44,7 @@ use std::path::PathBuf; | ||||
| use env_logger::LogBuilder; | ||||
| use ctrlc::CtrlC; | ||||
| use util::*; | ||||
| use util::panics::MayPanic; | ||||
| use util::panics::{MayPanic, ForwardPanic, PanicHandler}; | ||||
| use ethcore::spec::*; | ||||
| use ethcore::client::*; | ||||
| use ethcore::service::{ClientService, NetSyncMessage}; | ||||
| @ -70,6 +71,7 @@ Parity. Ethereum Client. | ||||
| 
 | ||||
| Usage: | ||||
|   parity daemon <pid-file> [options] [ --no-bootstrap | <enode>... ] | ||||
|   parity account (new | list) | ||||
|   parity [options] [ --no-bootstrap | <enode>... ] | ||||
| 
 | ||||
| Protocol Options: | ||||
| @ -79,6 +81,7 @@ Protocol Options: | ||||
|   --networkid INDEX        Override the network identifier from the chain we are on. | ||||
|   --archive                Client should not prune the state/storage trie. | ||||
|   -d --datadir PATH        Specify the database & configuration directory path [default: $HOME/.parity] | ||||
|   --keys-path PATH         Specify the path for JSON key files to be found [default: $HOME/.web3/keys] | ||||
|   --identity NAME          Specify your node's name. | ||||
| 
 | ||||
| Networking Options: | ||||
| @ -125,11 +128,14 @@ Miscellaneous Options: | ||||
| #[derive(Debug, RustcDecodable)] | ||||
| struct Args { | ||||
| 	cmd_daemon: bool, | ||||
| 	cmd_account: bool, | ||||
| 	cmd_new: bool, | ||||
| 	cmd_list: bool, | ||||
| 	arg_pid_file: String, | ||||
| 	arg_enode: Vec<String>, | ||||
| 	flag_chain: String, | ||||
| 	flag_testnet: bool, | ||||
| 	flag_db_path: String, | ||||
| 	flag_datadir: String, | ||||
| 	flag_networkid: Option<String>, | ||||
| 	flag_identity: String, | ||||
| 	flag_cache: Option<usize>, | ||||
| @ -189,10 +195,10 @@ fn setup_log(init: &Option<String>) { | ||||
| } | ||||
| 
 | ||||
| #[cfg(feature = "rpc")] | ||||
| fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_domain: &str, apis: Vec<&str>) { | ||||
| fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_domain: &str, apis: Vec<&str>) -> Option<Arc<PanicHandler>> { | ||||
| 	use rpc::v1::*; | ||||
| 
 | ||||
| 	let mut server = rpc::HttpServer::new(1); | ||||
| 	let server = rpc::RpcServer::new(); | ||||
| 	for api in apis.into_iter() { | ||||
| 		match api { | ||||
| 			"web3" => server.add_delegate(Web3Client::new().to_delegate()), | ||||
| @ -206,11 +212,12 @@ fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_dom | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	server.start_async(url, cors_domain); | ||||
| 	Some(server.start_http(url, cors_domain, 1)) | ||||
| } | ||||
| 
 | ||||
| #[cfg(not(feature = "rpc"))] | ||||
| fn setup_rpc_server(_client: Arc<Client>, _sync: Arc<EthSync>, _url: &str) { | ||||
| fn setup_rpc_server(_client: Arc<Client>, _sync: Arc<EthSync>, _url: &str) -> Option<Arc<PanicHandler>> { | ||||
| 	None | ||||
| } | ||||
| 
 | ||||
| fn print_version() { | ||||
| @ -238,7 +245,7 @@ impl Configuration { | ||||
| 	} | ||||
| 
 | ||||
| 	fn path(&self) -> String { | ||||
| 		self.args.flag_db_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) | ||||
| 		self.args.flag_datadir.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) | ||||
| 	} | ||||
| 
 | ||||
| 	fn author(&self) -> Address { | ||||
| @ -335,10 +342,44 @@ impl Configuration { | ||||
| 				.start() | ||||
| 				.unwrap_or_else(|e| die!("Couldn't daemonize; {}", e)); | ||||
| 		} | ||||
| 		if self.args.cmd_account { | ||||
| 			self.execute_account_cli(); | ||||
| 			return; | ||||
| 		} | ||||
| 		self.execute_client(); | ||||
| 	} | ||||
| 
 | ||||
| 	fn execute_account_cli(&self) { | ||||
| 		use util::keys::store::SecretStore; | ||||
| 		use rpassword::read_password; | ||||
| 		let mut secret_store = SecretStore::new(); | ||||
| 		if self.args.cmd_new { | ||||
| 			println!("Please note that password is NOT RECOVERABLE."); | ||||
| 			println!("Type password: "); | ||||
| 			let password = read_password().unwrap(); | ||||
| 			println!("Repeat password: "); | ||||
| 			let password_repeat = read_password().unwrap(); | ||||
| 			if password != password_repeat { | ||||
| 				println!("Passwords do not match!"); | ||||
| 				return; | ||||
| 			} | ||||
| 			println!("New account address:"); | ||||
| 			let new_address = secret_store.new_account(&password).unwrap(); | ||||
| 			println!("{:?}", new_address); | ||||
| 			return; | ||||
| 		} | ||||
| 		if self.args.cmd_list { | ||||
| 			println!("Known addresses:"); | ||||
| 			for &(addr, _) in secret_store.accounts().unwrap().iter() { | ||||
| 				println!("{:?}", addr); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	fn execute_client(&self) { | ||||
| 		// Setup panic handler
 | ||||
| 		let panic_handler = PanicHandler::new_in_arc(); | ||||
| 
 | ||||
| 		// Setup logging
 | ||||
| 		setup_log(&self.args.flag_logging); | ||||
| 		// Raise fdlimit
 | ||||
| @ -365,6 +406,7 @@ impl Configuration { | ||||
| 		client_config.name = self.args.flag_identity.clone(); | ||||
| 		client_config.queue.max_mem_use = self.args.flag_queue_max_size; | ||||
| 		let mut service = ClientService::start(client_config, spec, net_settings, &Path::new(&self.path())).unwrap(); | ||||
| 		panic_handler.forward_from(&service); | ||||
| 		let client = service.client().clone(); | ||||
| 		client.set_author(self.author()); | ||||
| 		client.set_extra_data(self.extra_data()); | ||||
| @ -382,30 +424,36 @@ impl Configuration { | ||||
| 			let cors = self.args.flag_rpccorsdomain.as_ref().unwrap_or(&self.args.flag_jsonrpc_cors); | ||||
| 			// TODO: use this as the API list.
 | ||||
| 			let apis = self.args.flag_rpcapi.as_ref().unwrap_or(&self.args.flag_jsonrpc_apis); | ||||
| 			setup_rpc_server(service.client(), sync.clone(), &url, cors, apis.split(",").collect()); | ||||
| 			let server_handler = setup_rpc_server(service.client(), sync.clone(), &url, cors, apis.split(",").collect()); | ||||
| 			if let Some(handler) = server_handler { | ||||
| 				panic_handler.forward_from(handler.deref()); | ||||
| 			} | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 		// Register IO handler
 | ||||
| 		let io_handler  = Arc::new(ClientIoHandler { | ||||
| 			client: service.client(), | ||||
| 			info: Default::default(), | ||||
| 			sync: sync | ||||
| 			sync: sync.clone(), | ||||
| 		}); | ||||
| 		service.io().register_handler(io_handler).expect("Error registering IO handler"); | ||||
| 
 | ||||
| 		// Handle exit
 | ||||
| 		wait_for_exit(&service); | ||||
| 		wait_for_exit(panic_handler); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn wait_for_exit(client_service: &ClientService) { | ||||
| fn wait_for_exit(panic_handler: Arc<PanicHandler>) { | ||||
| 	let exit = Arc::new(Condvar::new()); | ||||
| 
 | ||||
| 	// Handle possible exits
 | ||||
| 	let e = exit.clone(); | ||||
| 	CtrlC::set_handler(move || { e.notify_all(); }); | ||||
| 
 | ||||
| 	// Handle panics
 | ||||
| 	let e = exit.clone(); | ||||
| 	client_service.on_panic(move |_reason| { e.notify_all(); }); | ||||
| 	panic_handler.on_panic(move |_reason| { e.notify_all(); }); | ||||
| 
 | ||||
| 	// Wait for signal
 | ||||
| 	let mutex = Mutex::new(()); | ||||
|  | ||||
| @ -12,8 +12,8 @@ build = "build.rs" | ||||
| log = "0.3" | ||||
| serde = "0.7.0" | ||||
| serde_json = "0.7.0" | ||||
| jsonrpc-core = "1.2" | ||||
| jsonrpc-http-server = "2.1" | ||||
| jsonrpc-core = "2.0" | ||||
| jsonrpc-http-server = "3.0" | ||||
| ethcore-util = { path = "../util" } | ||||
| ethcore = { path = "../ethcore" } | ||||
| ethash = { path = "../ethash" } | ||||
|  | ||||
| @ -29,33 +29,43 @@ extern crate ethcore; | ||||
| extern crate ethsync; | ||||
| extern crate transient_hashmap; | ||||
| 
 | ||||
| use std::sync::Arc; | ||||
| use std::thread; | ||||
| use util::panics::PanicHandler; | ||||
| use self::jsonrpc_core::{IoHandler, IoDelegate}; | ||||
| 
 | ||||
| pub mod v1; | ||||
| 
 | ||||
| /// Http server.
 | ||||
| pub struct HttpServer { | ||||
| 	handler: IoHandler, | ||||
| 	threads: usize | ||||
| pub struct RpcServer { | ||||
| 	handler: Arc<IoHandler>, | ||||
| } | ||||
| 
 | ||||
| impl HttpServer { | ||||
| impl RpcServer { | ||||
| 	/// Construct new http server object with given number of threads.
 | ||||
| 	pub fn new(threads: usize) -> HttpServer { | ||||
| 		HttpServer { | ||||
| 			handler: IoHandler::new(), | ||||
| 			threads: threads | ||||
| 	pub fn new() -> RpcServer { | ||||
| 		RpcServer { | ||||
| 			handler: Arc::new(IoHandler::new()), | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Add io delegate.
 | ||||
| 	pub fn add_delegate<D>(&mut self, delegate: IoDelegate<D>) where D: Send + Sync + 'static { | ||||
| 	pub fn add_delegate<D>(&self, delegate: IoDelegate<D>) where D: Send + Sync + 'static { | ||||
| 		self.handler.add_delegate(delegate); | ||||
| 	} | ||||
| 
 | ||||
| 	/// Start server asynchronously in new thread
 | ||||
| 	pub fn start_async(self, addr: &str, cors_domain: &str) { | ||||
| 		let server = jsonrpc_http_server::Server::new(self.handler, self.threads); | ||||
| 		server.start_async(addr, jsonrpc_http_server::AccessControlAllowOrigin::Value(cors_domain.to_owned())) | ||||
| 	/// Start server asynchronously in new thread and returns panic handler.
 | ||||
| 	pub fn start_http(&self, addr: &str, cors_domain: &str, threads: usize) -> Arc<PanicHandler> { | ||||
| 		let addr = addr.to_owned(); | ||||
| 		let cors_domain = cors_domain.to_owned(); | ||||
| 		let panic_handler = PanicHandler::new_in_arc(); | ||||
| 		let ph = panic_handler.clone(); | ||||
| 		let server = jsonrpc_http_server::Server::new(self.handler.clone()); | ||||
| 		thread::Builder::new().name("jsonrpc_http".to_string()).spawn(move || { | ||||
| 			ph.catch_panic(move || { | ||||
| 				server.start(addr.as_ref(), jsonrpc_http_server::AccessControlAllowOrigin::Value(cors_domain), threads); | ||||
| 			}).unwrap() | ||||
| 		}).expect("Error while creating jsonrpc http thread"); | ||||
| 		panic_handler | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -853,8 +853,8 @@ impl ChainSync { | ||||
| 			self.downloading_bodies.remove(&n); | ||||
| 			self.downloading_headers.remove(&n); | ||||
| 		} | ||||
| 		self.headers.remove_tail(&start); | ||||
| 		self.bodies.remove_tail(&start); | ||||
| 		self.headers.remove_from(&start); | ||||
| 		self.bodies.remove_from(&start); | ||||
| 	} | ||||
| 
 | ||||
| 	/// Request headers from a peer by block hash
 | ||||
|  | ||||
| @ -42,6 +42,8 @@ pub trait RangeCollection<K, V> { | ||||
| 	fn remove_head(&mut self, start: &K); | ||||
| 	/// Remove all elements >= `start` in the range that contains `start`
 | ||||
| 	fn remove_tail(&mut self, start: &K); | ||||
| 	/// Remove all elements >= `start` 
 | ||||
| 	fn remove_from(&mut self, start: &K); | ||||
| 	/// Remove all elements >= `tail`
 | ||||
| 	fn insert_item(&mut self, key: K, value: V); | ||||
| 	/// Get an iterator over ranges
 | ||||
| @ -137,6 +139,28 @@ impl<K, V> RangeCollection<K, V> for Vec<(K, Vec<V>)> where K: Ord + PartialEq + | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Remove the element and all following it.
 | ||||
| 	fn remove_from(&mut self, key: &K) { | ||||
| 		match self.binary_search_by(|&(k, _)| k.cmp(key).reverse()) { | ||||
| 			Ok(index) => { self.drain(.. index + 1); }, | ||||
| 			Err(index) =>{ | ||||
| 				let mut empty = false; | ||||
| 				match self.get_mut(index) { | ||||
| 					Some(&mut (ref k, ref mut v)) if k <= key && (*k + FromUsize::from_usize(v.len())) > *key => { | ||||
| 						v.truncate((*key - *k).to_usize()); | ||||
| 						empty = v.is_empty(); | ||||
| 					} | ||||
| 					_ => {} | ||||
| 				} | ||||
| 				if empty { | ||||
| 					self.drain(.. index + 1); | ||||
| 				} else { | ||||
| 					self.drain(.. index); | ||||
| 				} | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Remove range elements up to key
 | ||||
| 	fn remove_head(&mut self, key: &K) { | ||||
| 		if *key == FromUsize::from_usize(0) { | ||||
| @ -272,5 +296,17 @@ fn test_range() { | ||||
| 	assert_eq!(r.range_iter().cmp(vec![(2, &['b'][..])]),  Ordering::Equal); | ||||
| 	r.remove_tail(&2); | ||||
| 	assert_eq!(r.range_iter().next(), None); | ||||
| 
 | ||||
| 	let mut r = ranges.clone(); | ||||
| 	r.remove_from(&20); | ||||
| 	assert_eq!(r.range_iter().cmp(vec![(2, &['b', 'c', 'd'][..]),  (16, &['p', 'q', 'r'][..])]),  Ordering::Equal); | ||||
| 	r.remove_from(&17); | ||||
| 	assert_eq!(r.range_iter().cmp(vec![(2, &['b', 'c', 'd'][..]),  (16, &['p'][..])]),  Ordering::Equal); | ||||
| 	r.remove_from(&15); | ||||
| 	assert_eq!(r.range_iter().cmp(vec![(2, &['b', 'c', 'd'][..])]),  Ordering::Equal); | ||||
| 	r.remove_from(&3); | ||||
| 	assert_eq!(r.range_iter().cmp(vec![(2, &['b'][..])]),  Ordering::Equal); | ||||
| 	r.remove_from(&2); | ||||
| 	assert_eq!(r.range_iter().next(), None); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -84,6 +84,7 @@ impl SecretStore { | ||||
| 		let mut path = ::std::env::home_dir().expect("Failed to get home dir"); | ||||
| 		path.push(".parity"); | ||||
| 		path.push("keys"); | ||||
| 		::std::fs::create_dir_all(&path).expect("Should panic since it is critical to be able to access home dir"); | ||||
| 		Self::new_in(&path) | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user