Improve capability information and disable old clients.
This commit is contained in:
parent
74a6203f72
commit
22cb5753d0
@ -127,6 +127,7 @@ impl SleepState {
|
|||||||
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
||||||
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
|
enabled: AtomicBool,
|
||||||
mode: Mutex<Mode>,
|
mode: Mutex<Mode>,
|
||||||
chain: RwLock<Arc<BlockChain>>,
|
chain: RwLock<Arc<BlockChain>>,
|
||||||
tracedb: RwLock<TraceDB<BlockChain>>,
|
tracedb: RwLock<TraceDB<BlockChain>>,
|
||||||
@ -164,6 +165,7 @@ impl Client {
|
|||||||
message_channel: IoChannel<ClientIoMessage>,
|
message_channel: IoChannel<ClientIoMessage>,
|
||||||
db_config: &DatabaseConfig,
|
db_config: &DatabaseConfig,
|
||||||
) -> Result<Arc<Client>, ClientError> {
|
) -> Result<Arc<Client>, ClientError> {
|
||||||
|
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
let gb = spec.genesis_block();
|
let gb = spec.genesis_block();
|
||||||
|
|
||||||
@ -226,6 +228,7 @@ impl Client {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let client = Arc::new(Client {
|
let client = Arc::new(Client {
|
||||||
|
enabled: AtomicBool::new(true),
|
||||||
sleep_state: Mutex::new(SleepState::new(awake)),
|
sleep_state: Mutex::new(SleepState::new(awake)),
|
||||||
liveness: AtomicBool::new(awake),
|
liveness: AtomicBool::new(awake),
|
||||||
mode: Mutex::new(config.mode.clone()),
|
mode: Mutex::new(config.mode.clone()),
|
||||||
@ -411,6 +414,12 @@ impl Client {
|
|||||||
|
|
||||||
/// This is triggered by a message coming from a block queue when the block is ready for insertion
|
/// This is triggered by a message coming from a block queue when the block is ready for insertion
|
||||||
pub fn import_verified_blocks(&self) -> usize {
|
pub fn import_verified_blocks(&self) -> usize {
|
||||||
|
|
||||||
|
// Shortcut out if we know we're incapable of syncing the chain.
|
||||||
|
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
let max_blocks_to_import = 4;
|
let max_blocks_to_import = 4;
|
||||||
let (imported_blocks, import_results, invalid_blocks, imported, duration, is_empty) = {
|
let (imported_blocks, import_results, invalid_blocks, imported, duration, is_empty) = {
|
||||||
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
||||||
@ -909,8 +918,16 @@ impl BlockChainClient for Client {
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disable(&self) {
|
||||||
|
self.set_mode(IpcMode::Off);
|
||||||
|
self.enabled.store(false, AtomicOrdering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
fn set_mode(&self, new_mode: IpcMode) {
|
fn set_mode(&self, new_mode: IpcMode) {
|
||||||
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
|
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
|
||||||
|
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let mut mode = self.mode.lock();
|
let mut mode = self.mode.lock();
|
||||||
*mode = new_mode.clone().into();
|
*mode = new_mode.clone().into();
|
||||||
|
@ -677,6 +677,8 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
|
|
||||||
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
||||||
|
|
||||||
|
fn disable(&self) { unimplemented!(); }
|
||||||
|
|
||||||
fn pruning_info(&self) -> PruningInfo {
|
fn pruning_info(&self) -> PruningInfo {
|
||||||
PruningInfo {
|
PruningInfo {
|
||||||
earliest_chain: 1,
|
earliest_chain: 1,
|
||||||
|
@ -54,7 +54,7 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
|
|
||||||
/// Look up the block number for the given block ID.
|
/// Look up the block number for the given block ID.
|
||||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
||||||
|
|
||||||
/// Get raw block body data by block id.
|
/// Get raw block body data by block id.
|
||||||
/// Block body is an RLP list of two items: uncles and transactions.
|
/// Block body is an RLP list of two items: uncles and transactions.
|
||||||
fn block_body(&self, id: BlockId) -> Option<Bytes>;
|
fn block_body(&self, id: BlockId) -> Option<Bytes>;
|
||||||
@ -252,6 +252,10 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Set the mode.
|
/// Set the mode.
|
||||||
fn set_mode(&self, mode: Mode);
|
fn set_mode(&self, mode: Mode);
|
||||||
|
|
||||||
|
/// Disable the client from importing blocks. This cannot be undone in this session and indicates
|
||||||
|
/// that a subsystem has reason to believe this executable incapable of syncing the chain.
|
||||||
|
fn disable(&self);
|
||||||
|
|
||||||
/// Returns engine-related extra info for `BlockId`.
|
/// Returns engine-related extra info for `BlockId`.
|
||||||
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>>;
|
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>>;
|
||||||
|
|
||||||
|
@ -282,7 +282,6 @@ impl Configuration {
|
|||||||
no_periodic_snapshot: self.args.flag_no_periodic_snapshot,
|
no_periodic_snapshot: self.args.flag_no_periodic_snapshot,
|
||||||
check_seal: !self.args.flag_no_seal_check,
|
check_seal: !self.args.flag_no_seal_check,
|
||||||
download_old_blocks: !self.args.flag_no_ancient_blocks,
|
download_old_blocks: !self.args.flag_no_ancient_blocks,
|
||||||
require_consensus: !self.args.flag_no_consensus,
|
|
||||||
serve_light: self.args.flag_serve_light,
|
serve_light: self.args.flag_serve_light,
|
||||||
verifier_settings: verifier_settings,
|
verifier_settings: verifier_settings,
|
||||||
};
|
};
|
||||||
@ -628,6 +627,7 @@ impl Configuration {
|
|||||||
fn update_policy(&self) -> Result<UpdatePolicy, String> {
|
fn update_policy(&self) -> Result<UpdatePolicy, String> {
|
||||||
Ok(UpdatePolicy {
|
Ok(UpdatePolicy {
|
||||||
enable_downloading: !self.args.flag_no_download,
|
enable_downloading: !self.args.flag_no_download,
|
||||||
|
require_consensus: !self.args.flag_no_consensus,
|
||||||
filter: match self.args.flag_auto_update.as_ref() {
|
filter: match self.args.flag_auto_update.as_ref() {
|
||||||
"none" => UpdateFilter::None,
|
"none" => UpdateFilter::None,
|
||||||
"critical" => UpdateFilter::Critical,
|
"critical" => UpdateFilter::Critical,
|
||||||
@ -943,7 +943,7 @@ mod tests {
|
|||||||
acc_conf: Default::default(),
|
acc_conf: Default::default(),
|
||||||
gas_pricer: Default::default(),
|
gas_pricer: Default::default(),
|
||||||
miner_extras: Default::default(),
|
miner_extras: Default::default(),
|
||||||
update_policy: UpdatePolicy { enable_downloading: true, filter: UpdateFilter::Critical },
|
update_policy: UpdatePolicy { enable_downloading: true, require_consensus: true, filter: UpdateFilter::Critical },
|
||||||
mode: Default::default(),
|
mode: Default::default(),
|
||||||
tracing: Default::default(),
|
tracing: Default::default(),
|
||||||
compaction: Default::default(),
|
compaction: Default::default(),
|
||||||
@ -961,7 +961,6 @@ mod tests {
|
|||||||
no_periodic_snapshot: false,
|
no_periodic_snapshot: false,
|
||||||
check_seal: true,
|
check_seal: true,
|
||||||
download_old_blocks: true,
|
download_old_blocks: true,
|
||||||
require_consensus: true,
|
|
||||||
serve_light: false,
|
serve_light: false,
|
||||||
verifier_settings: Default::default(),
|
verifier_settings: Default::default(),
|
||||||
}));
|
}));
|
||||||
@ -992,14 +991,14 @@ mod tests {
|
|||||||
fn should_parse_updater_options() {
|
fn should_parse_updater_options() {
|
||||||
// when
|
// when
|
||||||
let conf0 = parse(&["parity"]);
|
let conf0 = parse(&["parity"]);
|
||||||
let conf1 = parse(&["parity", "--auto-update", "all"]);
|
let conf1 = parse(&["parity", "--auto-update", "all", "--no-consensus"]);
|
||||||
let conf2 = parse(&["parity", "--no-download", "--auto-update=all"]);
|
let conf2 = parse(&["parity", "--no-download", "--auto-update=all"]);
|
||||||
let conf3 = parse(&["parity", "--auto-update=xxx"]);
|
let conf3 = parse(&["parity", "--auto-update=xxx"]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, filter: UpdateFilter::Critical});
|
assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, require_consensus: true, filter: UpdateFilter::Critical});
|
||||||
assert_eq!(conf1.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, filter: UpdateFilter::All});
|
assert_eq!(conf1.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, require_consensus: false, filter: UpdateFilter::All});
|
||||||
assert_eq!(conf2.update_policy().unwrap(), UpdatePolicy{enable_downloading: false, filter: UpdateFilter::All});
|
assert_eq!(conf2.update_policy().unwrap(), UpdatePolicy{enable_downloading: false, require_consensus: true, filter: UpdateFilter::All});
|
||||||
assert!(conf3.update_policy().is_err());
|
assert!(conf3.update_policy().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,6 @@ pub struct RunCmd {
|
|||||||
pub no_periodic_snapshot: bool,
|
pub no_periodic_snapshot: bool,
|
||||||
pub check_seal: bool,
|
pub check_seal: bool,
|
||||||
pub download_old_blocks: bool,
|
pub download_old_blocks: bool,
|
||||||
pub require_consensus: bool,
|
|
||||||
pub serve_light: bool,
|
pub serve_light: bool,
|
||||||
pub verifier_settings: VerifierSettings,
|
pub verifier_settings: VerifierSettings,
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ pub enum UpdateFilter {
|
|||||||
pub struct UpdatePolicy {
|
pub struct UpdatePolicy {
|
||||||
/// Download potential updates.
|
/// Download potential updates.
|
||||||
pub enable_downloading: bool,
|
pub enable_downloading: bool,
|
||||||
|
/// Disable client if we know we're incapable of syncing.
|
||||||
|
pub require_consensus: bool,
|
||||||
/// Which of those downloaded should be automatically installed.
|
/// Which of those downloaded should be automatically installed.
|
||||||
pub filter: UpdateFilter,
|
pub filter: UpdateFilter,
|
||||||
}
|
}
|
||||||
@ -48,6 +50,7 @@ impl Default for UpdatePolicy {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
UpdatePolicy {
|
UpdatePolicy {
|
||||||
enable_downloading: false,
|
enable_downloading: false,
|
||||||
|
require_consensus: true,
|
||||||
filter: UpdateFilter::None,
|
filter: UpdateFilter::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,6 +84,23 @@ pub struct OperationsInfo {
|
|||||||
pub minor: Option<ReleaseInfo>,
|
pub minor: Option<ReleaseInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information on the current version's consensus capabililty.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum CapState {
|
||||||
|
/// Unknown.
|
||||||
|
Unknown,
|
||||||
|
/// Capable of consensus indefinitely.
|
||||||
|
Capable,
|
||||||
|
/// Capable of consensus up until a definite block.
|
||||||
|
CapableUntil(u64),
|
||||||
|
/// Incapable of consensus since a particular block.
|
||||||
|
IncapableSince(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CapState {
|
||||||
|
fn default() -> Self { CapState::Unknown }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct UpdaterState {
|
struct UpdaterState {
|
||||||
latest: Option<OperationsInfo>,
|
latest: Option<OperationsInfo>,
|
||||||
@ -88,6 +108,8 @@ struct UpdaterState {
|
|||||||
fetching: Option<ReleaseInfo>,
|
fetching: Option<ReleaseInfo>,
|
||||||
ready: Option<ReleaseInfo>,
|
ready: Option<ReleaseInfo>,
|
||||||
installed: Option<ReleaseInfo>,
|
installed: Option<ReleaseInfo>,
|
||||||
|
|
||||||
|
capability: CapState,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Service for checking for updates and determining whether we can achieve consensus.
|
/// Service for checking for updates and determining whether we can achieve consensus.
|
||||||
@ -135,18 +157,16 @@ impl Updater {
|
|||||||
let r = Arc::new(u);
|
let r = Arc::new(u);
|
||||||
*r.fetcher.lock() = Some(fetch::Client::new(r.clone()));
|
*r.fetcher.lock() = Some(fetch::Client::new(r.clone()));
|
||||||
*r.weak_self.lock() = Arc::downgrade(&r);
|
*r.weak_self.lock() = Arc::downgrade(&r);
|
||||||
|
|
||||||
|
r.poll();
|
||||||
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the currently running client capable of supporting the current chain?
|
/// Is the currently running client capable of supporting the current chain?
|
||||||
/// `Some` answer or `None` if information on the running client is not available.
|
/// We default to true if there's no clear information.
|
||||||
pub fn is_capable(&self) -> Option<bool> {
|
pub fn capability(&self) -> CapState {
|
||||||
self.state.lock().latest.as_ref().and_then(|latest| {
|
self.state.lock().capability
|
||||||
latest.this_fork.map(|this_fork| {
|
|
||||||
let current_number = self.client.upgrade().map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0));
|
|
||||||
this_fork >= latest.fork || current_number < latest.fork
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The release which is ready to be upgraded to, if any. If this returns `Some`, then
|
/// The release which is ready to be upgraded to, if any. If this returns `Some`, then
|
||||||
@ -294,6 +314,7 @@ impl Updater {
|
|||||||
|
|
||||||
let current_number = self.client.upgrade().map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0));
|
let current_number = self.client.upgrade().map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0));
|
||||||
|
|
||||||
|
let mut capability = CapState::Unknown;
|
||||||
let latest = self.collect_latest().ok();
|
let latest = self.collect_latest().ok();
|
||||||
if let Some(ref latest) = latest {
|
if let Some(ref latest) = latest {
|
||||||
info!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})",
|
info!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})",
|
||||||
@ -321,8 +342,31 @@ impl Updater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
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);
|
||||||
|
|
||||||
|
if let Some(this_fork) = latest.this_fork {
|
||||||
|
if this_fork < latest.fork {
|
||||||
|
// We're behind the latest fork. Now is the time to be upgrading; perhaps we're too late...
|
||||||
|
if let Some(c) = self.client.upgrade() {
|
||||||
|
let current_number = c.block_number(BlockId::Latest).unwrap_or(0);
|
||||||
|
if current_number >= latest.fork - 1 {
|
||||||
|
// We're at (or past) the last block we can import. Disable the client.
|
||||||
|
if self.update_policy.require_consensus {
|
||||||
|
c.disable();
|
||||||
|
}
|
||||||
|
capability = CapState::IncapableSince(latest.fork);
|
||||||
|
} else {
|
||||||
|
capability = CapState::CapableUntil(latest.fork);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
capability = CapState::Capable;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(*self.state.lock()).latest = latest;
|
|
||||||
|
let mut s = self.state.lock();
|
||||||
|
s.latest = latest;
|
||||||
|
s.capability = capability;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user