diff --git a/Cargo.lock b/Cargo.lock index 722348c33..49871eeab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.5.0", "ethcore-dapps 1.5.0", "ethcore-devtools 1.5.0", diff --git a/Cargo.toml b/Cargo.toml index c3a44e1cc..b4020f198 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ ethcore-stratum = { path = "stratum" } ethcore-dapps = { path = "dapps", optional = true } clippy = { version = "0.0.103", optional = true} ethcore-light = { path = "ethcore/light" } +ethabi = "0.2.2" [target.'cfg(windows)'.dependencies] winapi = "0.2" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 092819300..7fa714e8f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -711,16 +711,6 @@ impl Client { } } - /// Look up the block number for the given block ID. - pub fn block_number(&self, id: BlockId) -> Option { - match id { - BlockId::Number(number) => Some(number), - BlockId::Hash(ref hash) => self.chain.read().block_number(hash), - BlockId::Earliest => Some(0), - BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()), - } - } - /// Take a snapshot at the given block. /// If the ID given is "latest", this will default to 1000 blocks behind. pub fn take_snapshot(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> { @@ -946,6 +936,15 @@ impl BlockChainClient for Client { Self::block_hash(&chain, id).and_then(|hash| chain.block_header_data(&hash)) } + fn block_number(&self, id: BlockId) -> Option { + match id { + BlockId::Number(number) => Some(number), + BlockId::Hash(ref hash) => self.chain.read().block_number(hash), + BlockId::Earliest => Some(0), + BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()), + } + } + fn block_body(&self, id: BlockId) -> Option { let chain = self.chain.read(); Self::block_hash(&chain, id).and_then(|hash| chain.block_body(&hash)) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index d2646b105..dd37a3c02 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -473,6 +473,10 @@ impl BlockChainClient for TestBlockChainClient { self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec())) } + fn block_number(&self, _id: BlockId) -> Option { + unimplemented!() + } + fn block_body(&self, id: BlockId) -> Option { self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| { let mut stream = RlpStream::new_list(2); diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index a6956461e..8f5d4c77a 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -52,6 +52,9 @@ pub trait BlockChainClient : Sync + Send { /// Get raw block header data by block id. fn block_header(&self, id: BlockId) -> Option; + /// Look up the block number for the given block ID. + fn block_number(&self, id: BlockId) -> Option; + /// Get raw block body data by block id. /// Block body is an RLP list of two items: uncles and transactions. fn block_body(&self, id: BlockId) -> Option; diff --git a/parity/blockchain.rs b/parity/blockchain.rs index d62f2b9bb..ffbe15068 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -178,7 +178,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result { // prepare client config let mut client_config = to_client_config( &cmd.cache_config, - Default::default(), Mode::Active, tracing, fat_db, @@ -345,7 +344,7 @@ fn start_client( try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.fork_path().as_path()))); // prepare client config - let client_config = to_client_config(&cache_config, Default::default(), Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true); + let client_config = to_client_config(&cache_config, Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true); let service = try!(ClientService::start( client_config, diff --git a/parity/configuration.rs b/parity/configuration.rs index ca3189827..c9358cd35 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -23,7 +23,7 @@ use cli::{Args, ArgsError}; use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address}; use util::log::Colour; use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP}; -use ethcore::client::{VMType, UpdatePolicy, UpdateFilter}; +use ethcore::client::{VMType}; use ethcore::miner::{MinerOptions, Banning}; use ethcore::verification::queue::VerifierSettings; @@ -37,6 +37,7 @@ use ethcore_logger::Config as LogConfig; use dir::Directories; use dapps::Configuration as DappsConfiguration; use signer::{Configuration as SignerConfiguration}; +use updater::{UpdatePolicy, UpdateFilter}; use run::RunCmd; use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState, DataFormat}; use presale::ImportWallet; diff --git a/parity/helpers.rs b/parity/helpers.rs index 25acfcc55..60a04bc45 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -20,7 +20,7 @@ use std::time::Duration; use std::fs::File; use util::{clean_0x, U256, Uint, Address, path, CompactionProfile}; use util::journaldb::Algorithm; -use ethcore::client::{UpdatePolicy, Mode, BlockId, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; +use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; use ethcore::miner::{PendingSet, GasLimit, PrioritizationStrategy}; use cache::CacheConfig; use dir::DatabaseDirectories; diff --git a/parity/informant.rs b/parity/informant.rs index 1f3f3862a..31f5c3e81 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -19,12 +19,14 @@ use self::ansi_term::Colour::{White, Yellow, Green, Cyan, Blue}; use self::ansi_term::Style; use std::sync::{Arc}; -use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; +use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::time::{Instant, Duration}; +use io::{TimerToken, IoContext, IoHandler}; use isatty::{stdout_isatty}; use ethsync::{SyncProvider, ManageNetwork}; use util::{Uint, RwLock, Mutex, H256, Colour}; use ethcore::client::*; +use ethcore::service::ClientIoMessage; use ethcore::views::BlockView; use ethcore::snapshot::service::Service as SnapshotService; use ethcore::snapshot::{RestorationStatus, SnapshotService as SS}; @@ -44,6 +46,7 @@ pub struct Informant { last_import: Mutex, skipped: AtomicUsize, skipped_txs: AtomicUsize, + in_shutdown: AtomicBool, } /// Format byte counts to standard denominations. @@ -82,9 +85,14 @@ impl Informant { last_import: Mutex::new(Instant::now()), skipped: AtomicUsize::new(0), skipped_txs: AtomicUsize::new(0), + in_shutdown: AtomicBool::new(false), } } + /// Signal that we're shutting down; no more output necessary. + pub fn shutdown(&self) { + self.in_shutdown.store(true, ::std::sync::atomic::Ordering::SeqCst); + } #[cfg_attr(feature="dev", allow(match_bool))] pub fn tick(&self) { @@ -222,14 +230,16 @@ impl ChainNotify for Informant { } } +const INFO_TIMER: TimerToken = 0; + impl IoHandler for Informant { fn initialize(&self, io: &IoContext) { io.register_timer(INFO_TIMER, 5000).expect("Error registering timer"); } fn timeout(&self, _io: &IoContext, timer: TimerToken) { - if timer == INFO_TIMER && !self.shutdown.load(Ordering::SeqCst) { - self.info.tick(); + if timer == INFO_TIMER && !self.in_shutdown.load(AtomicOrdering::SeqCst) { + self.tick(); } } } diff --git a/parity/main.rs b/parity/main.rs index cf5ba7391..7d5426eb9 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -25,6 +25,7 @@ extern crate docopt; extern crate num_cpus; extern crate rustc_serialize; +extern crate ethabi; extern crate ethcore_devtools as devtools; extern crate ethcore; extern crate ethsync; @@ -87,7 +88,6 @@ mod upgrade; mod rpc; mod dapps; mod informant; -mod io_handler; mod cli; mod configuration; mod migration; @@ -111,7 +111,6 @@ mod boot; mod user_defaults; mod updater; mod operations; -mod fetch; #[cfg(feature="stratum")] mod stratum; @@ -254,12 +253,12 @@ fn main() { // if argv[0] == "parity" and this executable != ~/.parity-updates/parity, run that instead. let force_direct = std::env::args().any(|arg| arg == "--force-direct"); let exe = std::env::current_exe().ok(); - let development = exe.and_then(|p| p.parent().and_then(|p| p.parent()).and_then(|p| p.file_name()).map(|n| n == "target")).unwrap_or(false); - let same_name = exe.and_then(|p| p.file_stem().map_or(false, |s| s == "parity")); + let development = exe.as_ref().and_then(|p| p.parent().and_then(|p| p.parent()).and_then(|p| p.file_name()).map(|n| n == "target")).unwrap_or(false); + let same_name = exe.as_ref().and_then(|p| p.file_stem().map(|s| s == "parity")).unwrap_or(false); let have_update = updates_latest().exists(); - let is_non_updated_current = exe.map_or(false, p.canonicalize() != updates_latest().canonicalize()); - trace_main!("Starting up {} (force-direct: {}, development: {}, have-update: {}, non-updated-current: {})", std::env::current_exe().map(|x| format!("{}", x.display())).unwrap_or("".to_owned()), force_direct, development, have_update, is_non_updated_current); - if !force_direct && ! development && have_update && is_non_updated_current { + let is_non_updated_current = exe.map_or(false, |p| p.canonicalize().ok() != updates_latest().canonicalize().ok()); + trace_main!("Starting up {} (force-direct: {}, development: {}, same-name: {}, have-update: {}, non-updated-current: {})", std::env::current_exe().map(|x| format!("{}", x.display())).unwrap_or("".to_owned()), force_direct, development, same_name, have_update, is_non_updated_current); + if !force_direct && !development && same_name && have_update && is_non_updated_current { // looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise. // Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly. loop { diff --git a/parity/run.rs b/parity/run.rs index 2a7ecf12e..7d7fbff0c 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -14,16 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::{Arc, Mutex, Condvar}; +use std::sync::Arc; use std::net::{TcpListener}; use ctrlc::CtrlC; use fdlimit::raise_fd_limit; use ethcore_rpc::{NetworkSettings, is_major_importing}; use ethsync::NetworkConfiguration; -use util::{Colour, version, RotatingLogger}; +use util::{Colour, version, RotatingLogger, Mutex, Condvar}; use io::{MayPanic, ForwardPanic, PanicHandler}; use ethcore_logger::{Config as LogConfig}; -use ethcore::client::{Mode, UpdatePolicy, Updater, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient}; +use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockChainClient}; use ethcore::service::ClientService; use ethcore::account_provider::AccountProvider; use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions}; @@ -31,7 +31,7 @@ use ethcore::snapshot; use ethcore::verification::queue::VerifierSettings; use ethsync::SyncConfig; use informant::Informant; -use updater::Updater; +use updater::{UpdatePolicy, Updater}; use rpc::{HttpServer, IpcServer, HttpConfiguration, IpcConfiguration}; use signer::SignerServer; @@ -312,10 +312,8 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result } // the updater service - let updater = Updater::new(service.client(), update_policy); - if let Some(ref u) = updater { - service.add_notify(u.clone()); - } + let updater = Updater::new(Arc::downgrade(&(service.client() as Arc)), update_policy); + service.add_notify(updater.clone()); // set up dependencies for rpc servers let signer_path = cmd.signer_conf.signer_path.clone(); @@ -422,9 +420,9 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result info!("Finishing work, please wait..."); // to make sure timer does not spawn requests while shutdown is in progress - io_handler.shutdown.store(true, ::std::sync::atomic::Ordering::SeqCst); + informant.shutdown(); // just Arc is dropping here, to allow other reference release in its default time - drop(io_handler); + drop(informant); // hypervisor should be shutdown first while everything still works and can be // terminated gracefully @@ -474,7 +472,7 @@ fn wait_for_exit( _ipc_server: Option, _dapps_server: Option, _signer_server: Option, - updater: Option> + updater: Arc ) -> bool { let exit = Arc::new((Mutex::new(false), Condvar::new())); @@ -487,12 +485,11 @@ fn wait_for_exit( panic_handler.on_panic(move |_reason| { e.1.notify_all(); }); // Handle updater wanting to restart us - if let Some(ref u) = updater { - let e = exit.clone(); - u.set_exit_handler(move || { e.0.lock() = true; e.1.notify_all(); }); - } + let e = exit.clone(); + updater.set_exit_handler(move || { *e.0.lock() = true; e.1.notify_all(); }); // Wait for signal - let _ = exit.1.wait(exit.0.lock().unwrap()); - *exit.0.lock() + let mut l = exit.0.lock(); + let _ = exit.1.wait(&mut l); + *l } diff --git a/parity/snapshot.rs b/parity/snapshot.rs index d74adc1b4..804047596 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -170,7 +170,7 @@ impl SnapshotCommand { try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.fork_path().as_path()))); // prepare client config - let client_config = to_client_config(&self.cache_config, Default::default(), Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true); + let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true); let service = try!(ClientService::start( client_config, diff --git a/parity/updater.rs b/parity/updater.rs index 42def8b5a..85ceb7493 100644 --- a/parity/updater.rs +++ b/parity/updater.rs @@ -14,15 +14,14 @@ // 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::{Arc, Weak}; use std::{io, os, fs, env}; use std::path::{Path, PathBuf}; use util::misc::{VersionInfo, ReleaseTrack/*, platform*/}; -use util::{Address, H160, H256, FixedHash, Mutex}; +use util::{Address, H160, H256, FixedHash, Mutex, Bytes}; use super::operations::Operations; -use ethcore::client::{Client, BlockId}; -use fetch::HashFetch; -use fetch; +use ethcore::client::{BlockId, BlockChainClient, ChainNotify}; +use hash_fetch::{self as fetch, HashFetch}; /// Filter for releases. #[derive(Debug, Eq, PartialEq, Clone)] @@ -94,11 +93,11 @@ struct UpdaterState { pub struct Updater { // Useful environmental stuff. update_policy: UpdatePolicy, - weak_self: Weak, - client: Weak, + weak_self: Mutex>, + client: Weak, fetcher: Option, operations: Mutex>, - exit_handler: Mutex>, + exit_handler: Mutex>>, // Our version info (static) this: VersionInfo, @@ -128,7 +127,7 @@ impl Updater { pub fn new(client: Weak, update_policy: UpdatePolicy) -> Arc { let mut u = Updater { update_policy: update_policy, - weak_self: Default::default(), + weak_self: Mutex::new(Default::default()), client: client.clone(), fetcher: None, operations: Mutex::new(None), @@ -142,9 +141,9 @@ impl Updater { u.this.track = ReleaseTrack::Nightly; } - let r = Arc::new(u); - r.as_mut().weak_self = Arc::downgrade(&r); - r.as_mut().fetcher = Some(fetch::Client::new(r)); + let mut r = Arc::new(u); + Arc::get_mut(&mut r).expect("arc created on previous line; qed").fetcher = Some(fetch::Client::new(r.clone())); + *r.weak_self.lock() = Arc::downgrade(&r); r } @@ -167,9 +166,9 @@ impl Updater { /// Actually upgrades the client. Assumes that the binary has been downloaded. /// @returns `true` on success. - pub fn execute_upgrade(&mut self) -> bool { + pub fn execute_upgrade(&self) -> bool { (|| -> Result { - let s = state.lock(); + let mut s = self.state.lock(); if let Some(r) = s.ready.take() { let p = Self::update_file_path(&r.version); let n = Self::updates_latest(); @@ -178,7 +177,7 @@ impl Updater { Ok(_) => { info!("Completed upgrade to {}", &r.version); s.installed = Some(r); - if let Some(ref h) = self.exit_handler().lock() { + if let Some(ref h) = *self.exit_handler.lock() { (*h)(); } Ok(true) @@ -195,14 +194,6 @@ impl Updater { })().unwrap_or_else(|e| { warn!("{}", e); false }) } - /// Returns true iff the current version is capable of forming consensus. - pub fn is_consensus_capable(&self) -> bool { -/* if let Some(ref latest) = self.latest { - - -*/ unimplemented!() - } - /// Our version info. pub fn version_info(&self) -> &VersionInfo { &self.this } @@ -210,13 +201,13 @@ impl Updater { pub fn info(&self) -> Option { self.state.lock().latest.clone() } /// Set a closure to call when we want to restart the client - pub fn set_exit_handler(&self, f: Fn()) { - *self.exit_handler.lock() = f; + pub fn set_exit_handler(&self, f: F) where F: Fn() + 'static + Send { + *self.exit_handler.lock() = Some(Box::new(f)); } - fn collect_release_info(&self, release_id: &H256) -> Result { - let (fork, track, semver, is_critical) = self.operations.release(CLIENT_ID, release_id)?; - let latest_binary = self.operations.checksum(CLIENT_ID, release_id, &platform())?; + fn collect_release_info(operations: &Operations, release_id: &H256) -> Result { + let (fork, track, semver, is_critical) = operations.release(CLIENT_ID, release_id)?; + let latest_binary = operations.checksum(CLIENT_ID, release_id, &platform())?; Ok(ReleaseInfo { version: VersionInfo::from_raw(semver, track, release_id.clone().into()), is_critical: is_critical, @@ -226,32 +217,36 @@ impl Updater { } fn collect_latest(&self) -> Result { - let this_fork = u.operations.release(CLIENT_ID, &u.this.hash.into()).ok() - .and_then(|(fork, track, _, _)| if track > 0 {Some(fork as u64)} else {None}); + if let Some(ref operations) = *self.operations.lock() { + let this_fork = operations.release(CLIENT_ID, &self.this.hash.into()).ok() + .and_then(|(fork, track, _, _)| if track > 0 {Some(fork as u64)} else {None}); - if self.this.track == ReleaseTrack::Unknown { - return Err(format!("Current executable ({}) is unreleased.", H160::from(self.this.hash))); + if self.this.track == ReleaseTrack::Unknown { + return Err(format!("Current executable ({}) is unreleased.", H160::from(self.this.hash))); + } + + let latest_in_track = operations.latest_in_track(CLIENT_ID, self.this.track.into())?; + let in_track = Self::collect_release_info(operations, &latest_in_track)?; + let mut in_minor = Some(in_track.clone()); + const PROOF: &'static str = "in_minor initialised and assigned with Some; loop breaks if None assigned; qed"; + while in_minor.as_ref().expect(PROOF).version.track != self.this.track { + let track = match in_minor.as_ref().expect(PROOF).version.track { + ReleaseTrack::Beta => ReleaseTrack::Stable, + ReleaseTrack::Nightly => ReleaseTrack::Beta, + _ => { in_minor = None; break; } + }; + in_minor = Some(Self::collect_release_info(operations, &operations.latest_in_track(CLIENT_ID, track.into())?)?); + } + + Ok(OperationsInfo { + fork: operations.latest_fork()? as u64, + this_fork: this_fork, + track: in_track, + minor: in_minor, + }) + } else { + Err("Operations not available".into()) } - - let latest_in_track = self.operations.latest_in_track(CLIENT_ID, self.this.track.into())?; - let in_track = self.collect_release_info(&latest_in_track)?; - let mut in_minor = Some(in_track.clone()); - const PROOF: &'static str = "in_minor initialised and assigned with Some; loop breaks if None assigned; qed"; - while in_minor.as_ref().expect(PROOF).version.track != self.this.track { - let track = match in_minor.as_ref().expect(PROOF).version.track { - ReleaseTrack::Beta => ReleaseTrack::Stable, - ReleaseTrack::Nightly => ReleaseTrack::Beta, - _ => { in_minor = None; break; } - }; - in_minor = Some(self.collect_release_info(&self.operations.latest_in_track(CLIENT_ID, track.into())?)?); - } - - Ok(OperationsInfo { - fork: self.operations.latest_fork()? as u64, - this_fork: this_fork, - track: in_track, - minor: in_minor, - }) } fn update_file_path(v: &VersionInfo) -> PathBuf { @@ -268,10 +263,10 @@ impl Updater { dest } - fn fetch_done(&mut self, result: Result) { + fn fetch_done(&self, result: Result) { (|| -> Result<(), String> { let auto = { - let mut s = state.lock(); + let mut s = self.state.lock(); let fetched = s.fetching.take().unwrap(); let b = result.map_err(|e| format!("Unable to fetch update ({}): {:?}", fetched.version, e))?; info!("Fetched latest version ({}) OK to {}", fetched.version, b.display()); @@ -288,17 +283,18 @@ impl Updater { auto }; if auto { + // will lock self.state, so ensure it's outside of previous block. self.execute_upgrade(); } Ok(()) })().unwrap_or_else(|e| warn!("{}", e)); } - fn poll(&mut self) { + fn poll(&self) { info!(target: "updater", "Current release is {}", self.this); - if *self.operations.lock().is_none() { - if let Some(ops_addr) = client.upgrade().registry_address("operations") { + if self.operations.lock().is_none() { + if let Some(ops_addr) = self.client.upgrade().and_then(|c| c.registry_address("operations".into())) { trace!(target: "client", "Found operations at {}", ops_addr); let client = self.client.clone(); *self.operations.lock() = Some(Operations::new(ops_addr, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d)))); @@ -308,8 +304,6 @@ impl Updater { } } - u.latest = u.collect_latest().ok(); - let current_number = self.client.upgrade().map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0)); let latest = self.collect_latest().ok(); @@ -329,23 +323,23 @@ impl Updater { let already_have_latest = s.installed.as_ref().or(s.ready.as_ref()).map_or(false, |t| *t == latest.track); if self.update_policy.enable_downloading && !running_latest && !already_have_latest { if let Some(b) = latest.track.binary { - if fetching.is_none() { + if s.fetching.is_none() { info!("Attempting to get parity binary {}", b); s.fetching = Some(latest.track.clone()); - let weak_self = self.weak_self.clone(); - let f = move |r: Result| if let Some(this) = weak_self.upgrade().as_mut() { this.fetch_done(r) }}; - fetcher.fetch(b, Box::new(f)).ok(); + let weak_self = self.weak_self.lock().clone(); + let f = move |r: Result| if let Some(this) = weak_self.upgrade() { this.fetch_done(r) }; + self.fetcher.as_ref().expect("Created on `new`; qed").fetch(b, Box::new(f)).ok(); } } } - info!(target: "updater", "Fork: this/current/latest/latest-known: {}/#{}/#{}/#{}", match s.latest.this_fork { Some(f) => format!("#{}", f), None => "unknown".into(), }, current_number, s.latest.track.fork, s.latest.fork); + info!(target: "updater", "Fork: this/current/latest/latest-known: {}/#{}/#{}/#{}", match latest.this_fork { Some(f) => format!("#{}", f), None => "unknown".into(), }, current_number, latest.track.fork, latest.fork); } (*self.state.lock()).latest = latest; } } impl ChainNotify for Updater { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, duration: u64) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _duration: u64) { // TODO: something like this // if !self.client.upgrade().map_or(true, |c| c.is_major_syncing()) { self.poll();