From 597c3a477090a516af5e6fc90598fe4cda53cb11 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 13 Dec 2016 21:21:07 +0100 Subject: [PATCH] Ensure chain state is at threshold security level before looking for updates. --- ethcore/src/client/client.rs | 2 +- ethcore/src/types/blockchain_info.rs | 13 +++++++++++++ ethcore/src/types/security_level.rs | 24 ++++++++++++++++++------ updater/src/updater.rs | 5 +++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 55636f936..6583d77c6 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1377,7 +1377,7 @@ impl BlockChainClient for Client { self.registrar.lock().as_ref() .and_then(|r| r.get_address(&(name.as_bytes().sha3()), "A").ok()) .and_then(|a| if a.is_zero() { None } else { Some(a) }) - } + } } impl MiningBlockChainClient for Client { diff --git a/ethcore/src/types/blockchain_info.rs b/ethcore/src/types/blockchain_info.rs index 6757acf64..33657ff0e 100644 --- a/ethcore/src/types/blockchain_info.rs +++ b/ethcore/src/types/blockchain_info.rs @@ -18,6 +18,7 @@ use util::{U256, H256}; use header::BlockNumber; +use types::security_level::SecurityLevel; /// Information about the blockchain gathered together. #[derive(Clone, Debug, Binary)] @@ -41,3 +42,15 @@ pub struct BlockChainInfo { /// Number of the first block on the best sequence. pub first_block_number: Option, } + +impl BlockChainInfo { + /// Determine the security model for the current state. + pub fn security_level(&self) -> SecurityLevel { + // TODO: Detect SecurityLevel::FullState : https://github.com/ethcore/parity/issues/3834 + if self.ancient_block_number.is_none() || self.first_block_number.is_none() { + SecurityLevel::FullProofOfWork + } else { + SecurityLevel::PartialProofOfWork(self.best_block_number - self.first_block_number.expect("Guard condition means this is not none")) + } + } +} \ No newline at end of file diff --git a/ethcore/src/types/security_level.rs b/ethcore/src/types/security_level.rs index 555ddf195..0415b9bb1 100644 --- a/ethcore/src/types/security_level.rs +++ b/ethcore/src/types/security_level.rs @@ -16,13 +16,25 @@ //! Indication of how secure the chain is. +use header::BlockNumber; + /// Indication of how secure the chain is. #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Binary)] pub enum SecurityLevel { - /// Chain was synced through manually evaluating all transactions from genesis. - Full, - /// All blocks are known to have a valid PoW from genesis. - Continuous, - /// Some headers (the argument) are known to have a valid PoW from genesis. - Light(u64), + /// All blocks from genesis to chain head are known to have valid state transitions and PoW. + FullState, + /// All blocks from genesis to chain head are known to have a valid PoW. + FullProofOfWork, + /// Some recent headers (the argument) are known to have a valid PoW. + PartialProofOfWork(BlockNumber), } + +impl SecurityLevel { + /// `true` for `FullPoW`/`FullState`. + pub fn is_full(&self) -> bool { + match *self { + SecurityLevel::FullState | SecurityLevel::FullProofOfWork => true, + _ => false, + } + } +} \ No newline at end of file diff --git a/updater/src/updater.rs b/updater/src/updater.rs index 050e52be2..75637f139 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -214,6 +214,11 @@ impl Updater { fn poll(&self) { info!(target: "updater", "Current release is {} ({:?})", self.this, self.this.hash); + // We rely on a secure state. Bail if we're unsure about it. + if self.client.upgrade().map_or(true, |s| !s.chain_info().security_level().is_full()) { + return; + } + if self.operations.lock().is_none() { if let Some(ops_addr) = self.client.upgrade().and_then(|c| c.registry_address("operations".into())) { trace!(target: "updater", "Found operations at {}", ops_addr);