diff --git a/Cargo.lock b/Cargo.lock index f738d28b8..c8920f522 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,6 +287,7 @@ dependencies = [ "ethash 1.4.0", "ethcore-bloom-journal 0.1.0", "ethcore-devtools 1.4.0", + "ethcore-hash-fetch 1.5.0", "ethcore-io 1.5.0", "ethcore-ipc 1.4.0", "ethcore-ipc-codegen 1.4.0", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 7c6576672..dd1c796a2 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -34,6 +34,7 @@ ethash = { path = "../ethash" } ethcore-util = { path = "../util" } ethcore-io = { path = "../util/io" } ethcore-devtools = { path = "../devtools" } +ethcore-hash-fetch = { path = "./hash-fetch" } ethjson = { path = "../json" } ethcore-ipc = { path = "../ipc/rpc" } ethstore = { path = "../ethstore" } diff --git a/ethcore/hash-fetch/src/lib.rs b/ethcore/hash-fetch/src/lib.rs index ffb74b260..b566121f5 100644 --- a/ethcore/hash-fetch/src/lib.rs +++ b/ethcore/hash-fetch/src/lib.rs @@ -30,4 +30,4 @@ mod client; pub mod urlhint; -pub use client::{HashFetch, Client}; +pub use client::{HashFetch, Client, Error}; diff --git a/ethcore/src/client/operations.rs b/ethcore/src/client/operations.rs index e0408cdb0..2124884c7 100644 --- a/ethcore/src/client/operations.rs +++ b/ethcore/src/client/operations.rs @@ -9,10 +9,10 @@ use util::{FixedHash, Uint}; pub struct Operations { contract: ethabi::Contract, address: util::Address, - do_call: Box) -> Result, String> + Send + 'static>, + do_call: Box) -> Result, String> + Send + Sync + 'static>, } impl Operations { - pub fn new(address: util::Address, do_call: F) -> Self where F: Fn(util::Address, Vec) -> Result, String> + Send + 'static { + pub fn new(address: util::Address, do_call: F) -> Self where F: Fn(util::Address, Vec) -> Result, String> + Send + Sync + 'static { Operations { contract: ethabi::Contract::new(ethabi::Interface::load(b"[{\"constant\":false,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"resetClientOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_release\",\"type\":\"bytes32\"}],\"name\":\"isLatest\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_txid\",\"type\":\"bytes32\"}],\"name\":\"rejectTransaction\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_number\",\"type\":\"uint32\"},{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_hard\",\"type\":\"bool\"},{\"name\":\"_spec\",\"type\":\"bytes32\"}],\"name\":\"proposeFork\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"}],\"name\":\"removeClient\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_release\",\"type\":\"bytes32\"}],\"name\":\"release\",\"outputs\":[{\"name\":\"o_forkBlock\",\"type\":\"uint32\"},{\"name\":\"o_track\",\"type\":\"uint8\"},{\"name\":\"o_semver\",\"type\":\"uint24\"},{\"name\":\"o_critical\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_checksum\",\"type\":\"bytes32\"}],\"name\":\"build\",\"outputs\":[{\"name\":\"o_release\",\"type\":\"bytes32\"},{\"name\":\"o_platform\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rejectFork\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"client\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"},{\"name\":\"required\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"setClientOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"fork\",\"outputs\":[{\"name\":\"name\",\"type\":\"bytes32\"},{\"name\":\"spec\",\"type\":\"bytes32\"},{\"name\":\"hard\",\"type\":\"bool\"},{\"name\":\"ratified\",\"type\":\"bool\"},{\"name\":\"requiredCount\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_release\",\"type\":\"bytes32\"},{\"name\":\"_platform\",\"type\":\"bytes32\"},{\"name\":\"_checksum\",\"type\":\"bytes32\"}],\"name\":\"addChecksum\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_txid\",\"type\":\"bytes32\"}],\"name\":\"confirmTransaction\",\"outputs\":[{\"name\":\"txSuccess\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"proxy\",\"outputs\":[{\"name\":\"requiredCount\",\"type\":\"uint256\"},{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"gas\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"addClient\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"clientOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_txid\",\"type\":\"bytes32\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_data\",\"type\":\"bytes\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_gas\",\"type\":\"uint256\"}],\"name\":\"proposeTransaction\",\"outputs\":[{\"name\":\"txSuccess\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"grandOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_release\",\"type\":\"bytes32\"},{\"name\":\"_forkBlock\",\"type\":\"uint32\"},{\"name\":\"_track\",\"type\":\"uint8\"},{\"name\":\"_semver\",\"type\":\"uint24\"},{\"name\":\"_critical\",\"type\":\"bool\"}],\"name\":\"addRelease\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"acceptFork\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"clientsRequired\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_release\",\"type\":\"bytes32\"}],\"name\":\"track\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_r\",\"type\":\"bool\"}],\"name\":\"setClientRequired\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"latestFork\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_track\",\"type\":\"uint8\"}],\"name\":\"latestInTrack\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_client\",\"type\":\"bytes32\"},{\"name\":\"_release\",\"type\":\"bytes32\"},{\"name\":\"_platform\",\"type\":\"bytes32\"}],\"name\":\"checksum\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"proposedFork\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"type\":\"function\"}]").expect("JSON is autogenerated; qed")), address: address, diff --git a/ethcore/src/client/updater.rs b/ethcore/src/client/updater.rs index c21f47b4a..11bdc0b5c 100644 --- a/ethcore/src/client/updater.rs +++ b/ethcore/src/client/updater.rs @@ -14,11 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::Weak; +use std::sync::{Mutex, Weak, Arc}; +use std::path::PathBuf; use util::misc::{VersionInfo, ReleaseTrack, platform}; -use util::{Address, H160, H256, FixedHash}; +use std::str::FromStr; +use util::{Bytes, Address, H160, H256, FixedHash}; use client::operations::Operations; -use client::{Client, UpdatePolicy, BlockId}; +use client::{Client, BlockChainClient, UpdatePolicy, BlockId}; +use fetch::HashFetch; +use fetch; #[derive(Debug, Clone, PartialEq)] pub struct ReleaseInfo { @@ -40,6 +44,7 @@ pub struct Updater { client: Weak, operations: Operations, update_policy: UpdatePolicy, + fetch_handler: Mutex>, // These don't change pub this: VersionInfo, @@ -51,12 +56,38 @@ pub struct Updater { const CLIENT_ID: &'static str = "parity"; +struct FetchHandler { + client: Weak, +} + +impl fetch::urlhint::ContractClient for FetchHandler { + fn registrar(&self) -> Result { + self.client.upgrade().ok_or_else(|| "Client not available".to_owned())? + .additional_params() + .get("registrar") + .and_then(|s| Address::from_str(s).ok()) + .ok_or_else(|| "Registrar not available".into()) + } + + fn call(&self, address: Address, data: Bytes) -> Result { + self.client.upgrade().ok_or_else(|| "Client not available".to_owned())? + .call_contract(address, data) + } +} + +fn start_fetch(client: Weak, hash: H256, on_done: Box) + Send>) -> Result { + let f = fetch::Client::new(Arc::new(FetchHandler { client: client, })); + let r = f.fetch(hash, on_done); + r.map(|_| f) +} + impl Updater { pub fn new(client: Weak, operations: Address, update_policy: UpdatePolicy) -> Self { let mut u = Updater { client: client.clone(), operations: Operations::new(operations, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d))), update_policy: update_policy, + fetch_handler: Mutex::new(None), this: VersionInfo::this(), this_fork: None, latest: None, @@ -140,6 +171,12 @@ impl Updater { }) } + fn fetch_done(&self, _r: Result) { + if let Ok(mut x) = self.fetch_handler.lock() { + *x = None; + } + } + pub fn tick(&mut self) { info!(target: "updater", "Current release is {}", self.this); @@ -157,6 +194,15 @@ impl Updater { "unreleased".into() } ); + if let Some(b) = latest.track.binary { + if let Ok(mut fetch_handler) = self.fetch_handler.lock() { + if fetch_handler.is_none() { + let c = self.client.clone(); + let f = move |r: Result| if let Some(c) = c.upgrade() { c.updater().as_ref().expect("updater exists; updater only owned by client; qed").fetch_done(r); }; + *fetch_handler = start_fetch(self.client.clone(), b, Box::new(f)).ok(); + } + } + } info!(target: "updater", "Fork: this/current/latest/latest-known: {}/#{}/#{}/#{}", match self.this_fork { Some(f) => format!("#{}", f), None => "unknown".into(), }, current_number, latest.track.fork, latest.fork); } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 26db14744..c0ad612d2 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -103,6 +103,7 @@ extern crate ethcore_bloom_journal as bloom_journal; extern crate byteorder; extern crate transient_hashmap; extern crate linked_hash_map; +extern crate ethcore_hash_fetch as fetch; #[macro_use] extern crate log;