Fetch and place in updates path.
This commit is contained in:
parent
8903384840
commit
c2b6be95c8
@ -20,7 +20,7 @@
|
|||||||
use ethcore::blockchain_info::BlockChainInfo;
|
use ethcore::blockchain_info::BlockChainInfo;
|
||||||
use ethcore::client::{BlockChainClient, ProvingBlockChainClient};
|
use ethcore::client::{BlockChainClient, ProvingBlockChainClient};
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use ethcore::ids::BlockID;
|
use ethcore::ids::BlockId;
|
||||||
|
|
||||||
use util::{Bytes, H256};
|
use util::{Bytes, H256};
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
let best_num = self.chain_info().best_block_number;
|
let best_num = self.chain_info().best_block_number;
|
||||||
let start_num = req.block_num;
|
let start_num = req.block_num;
|
||||||
|
|
||||||
match self.block_hash(BlockID::Number(req.block_num)) {
|
match self.block_hash(BlockId::Number(req.block_num)) {
|
||||||
Some(hash) if hash == req.block_hash => {}
|
Some(hash) if hash == req.block_hash => {}
|
||||||
_=> {
|
_=> {
|
||||||
trace!(target: "les_provider", "unknown/non-canonical start block in header request: {:?}", (req.block_num, req.block_hash));
|
trace!(target: "les_provider", "unknown/non-canonical start block in header request: {:?}", (req.block_num, req.block_hash));
|
||||||
@ -108,7 +108,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
.map(|x: u64| x.saturating_mul(req.skip))
|
.map(|x: u64| x.saturating_mul(req.skip))
|
||||||
.take_while(|x| if req.reverse { x < &start_num } else { best_num - start_num < *x })
|
.take_while(|x| if req.reverse { x < &start_num } else { best_num - start_num < *x })
|
||||||
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
||||||
.map(|x| self.block_header(BlockID::Number(x)))
|
.map(|x| self.block_header(BlockId::Number(x)))
|
||||||
.take_while(|x| x.is_some())
|
.take_while(|x| x.is_some())
|
||||||
.flat_map(|x| x)
|
.flat_map(|x| x)
|
||||||
.collect()
|
.collect()
|
||||||
@ -116,7 +116,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
|
|
||||||
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes> {
|
fn block_bodies(&self, req: request::Bodies) -> Vec<Bytes> {
|
||||||
req.block_hashes.into_iter()
|
req.block_hashes.into_iter()
|
||||||
.map(|hash| self.block_body(BlockID::Hash(hash)))
|
.map(|hash| self.block_body(BlockId::Hash(hash)))
|
||||||
.map(|body| body.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
.map(|body| body.unwrap_or_else(|| ::rlp::EMPTY_LIST_RLP.to_vec()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -135,8 +135,8 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
|
|
||||||
for request in req.requests {
|
for request in req.requests {
|
||||||
let proof = match request.key2 {
|
let proof = match request.key2 {
|
||||||
Some(key2) => self.prove_storage(request.key1, key2, request.from_level, BlockID::Hash(request.block)),
|
Some(key2) => self.prove_storage(request.key1, key2, request.from_level, BlockId::Hash(request.block)),
|
||||||
None => self.prove_account(request.key1, request.from_level, BlockID::Hash(request.block)),
|
None => self.prove_account(request.key1, request.from_level, BlockId::Hash(request.block)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut stream = RlpStream::new_list(proof.len());
|
let mut stream = RlpStream::new_list(proof.len());
|
||||||
@ -153,7 +153,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes> {
|
fn contract_code(&self, req: request::ContractCodes) -> Vec<Bytes> {
|
||||||
req.code_requests.into_iter()
|
req.code_requests.into_iter()
|
||||||
.map(|req| {
|
.map(|req| {
|
||||||
self.code_by_hash(req.account_key, BlockID::Hash(req.block_hash))
|
self.code_by_hash(req.account_key, BlockId::Hash(req.block_hash))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -1445,19 +1445,19 @@ impl MayPanic for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProvingBlockChainClient for Client {
|
impl ProvingBlockChainClient for Client {
|
||||||
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
|
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockId) -> Vec<Bytes> {
|
||||||
self.state_at(id)
|
self.state_at(id)
|
||||||
.and_then(move |state| state.prove_storage(key1, key2, from_level).ok())
|
.and_then(move |state| state.prove_storage(key1, key2, from_level).ok())
|
||||||
.unwrap_or_else(Vec::new)
|
.unwrap_or_else(Vec::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prove_account(&self, key1: H256, from_level: u32, id: BlockID) -> Vec<Bytes> {
|
fn prove_account(&self, key1: H256, from_level: u32, id: BlockId) -> Vec<Bytes> {
|
||||||
self.state_at(id)
|
self.state_at(id)
|
||||||
.and_then(move |state| state.prove_account(key1, from_level).ok())
|
.and_then(move |state| state.prove_account(key1, from_level).ok())
|
||||||
.unwrap_or_else(Vec::new)
|
.unwrap_or_else(Vec::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code_by_hash(&self, account_key: H256, id: BlockID) -> Bytes {
|
fn code_by_hash(&self, account_key: H256, id: BlockId) -> Bytes {
|
||||||
self.state_at(id)
|
self.state_at(id)
|
||||||
.and_then(move |state| state.code_by_address_hash(account_key).ok())
|
.and_then(move |state| state.code_by_address_hash(account_key).ok())
|
||||||
.and_then(|x| x)
|
.and_then(|x| x)
|
||||||
|
@ -71,8 +71,6 @@ impl FromStr for DatabaseCompactionProfile {
|
|||||||
pub enum UpdateFilter {
|
pub enum UpdateFilter {
|
||||||
/// All releases following the same track.
|
/// All releases following the same track.
|
||||||
All,
|
All,
|
||||||
/// Only those of the same minor version potentially changing tracks.
|
|
||||||
Patch,
|
|
||||||
/// As with `All`, but only those which are known to be critical.
|
/// As with `All`, but only those which are known to be critical.
|
||||||
Critical,
|
Critical,
|
||||||
/// None.
|
/// None.
|
||||||
|
@ -285,15 +285,15 @@ pub trait ProvingBlockChainClient: BlockChainClient {
|
|||||||
/// Returns a vector of raw trie nodes (in order from the root) proving the storage query.
|
/// Returns a vector of raw trie nodes (in order from the root) proving the storage query.
|
||||||
/// Nodes after `from_level` may be omitted.
|
/// Nodes after `from_level` may be omitted.
|
||||||
/// An empty vector indicates unservable query.
|
/// An empty vector indicates unservable query.
|
||||||
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockID) -> Vec<Bytes>;
|
fn prove_storage(&self, key1: H256, key2: H256, from_level: u32, id: BlockId) -> Vec<Bytes>;
|
||||||
|
|
||||||
/// Prove account existence at a specific block id.
|
/// Prove account existence at a specific block id.
|
||||||
/// The key is the keccak hash of the account's address.
|
/// The key is the keccak hash of the account's address.
|
||||||
/// Returns a vector of raw trie nodes (in order from the root) proving the query.
|
/// Returns a vector of raw trie nodes (in order from the root) proving the query.
|
||||||
/// Nodes after `from_level` may be omitted.
|
/// Nodes after `from_level` may be omitted.
|
||||||
/// An empty vector indicates unservable query.
|
/// An empty vector indicates unservable query.
|
||||||
fn prove_account(&self, key1: H256, from_level: u32, id: BlockID) -> Vec<Bytes>;
|
fn prove_account(&self, key1: H256, from_level: u32, id: BlockId) -> Vec<Bytes>;
|
||||||
|
|
||||||
/// Get code by address hash.
|
/// Get code by address hash.
|
||||||
fn code_by_hash(&self, account_key: H256, id: BlockID) -> Bytes;
|
fn code_by_hash(&self, account_key: H256, id: BlockId) -> Bytes;
|
||||||
}
|
}
|
@ -15,11 +15,12 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::{Weak};
|
use std::sync::{Weak};
|
||||||
|
use std::{fs, env};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use util::misc::{VersionInfo, ReleaseTrack, platform};
|
use util::misc::{VersionInfo, ReleaseTrack/*, platform*/};
|
||||||
use util::{Address, H160, H256, FixedHash, Mutex};
|
use util::{Address, H160, H256, FixedHash, Mutex};
|
||||||
use client::operations::Operations;
|
use client::operations::Operations;
|
||||||
use client::{Client, UpdatePolicy, BlockId};
|
use client::{Client, UpdatePolicy, UpdateFilter, BlockId};
|
||||||
use fetch::HashFetch;
|
use fetch::HashFetch;
|
||||||
use fetch;
|
use fetch;
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ pub struct Updater {
|
|||||||
fetch: Weak<HashFetch>,
|
fetch: Weak<HashFetch>,
|
||||||
operations: Operations,
|
operations: Operations,
|
||||||
update_policy: UpdatePolicy,
|
update_policy: UpdatePolicy,
|
||||||
fetching: Mutex<bool>,
|
fetching: Mutex<Option<ReleaseInfo>>,
|
||||||
|
|
||||||
// These don't change
|
// These don't change
|
||||||
pub this: VersionInfo,
|
pub this: VersionInfo,
|
||||||
@ -52,10 +53,16 @@ pub struct Updater {
|
|||||||
|
|
||||||
// This does change
|
// This does change
|
||||||
pub latest: Option<OperationsInfo>,
|
pub latest: Option<OperationsInfo>,
|
||||||
|
pub ready: Option<ReleaseInfo>,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLIENT_ID: &'static str = "parity";
|
const CLIENT_ID: &'static str = "parity";
|
||||||
|
|
||||||
|
fn platform() -> String {
|
||||||
|
"test".to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
impl Updater {
|
impl Updater {
|
||||||
pub fn new(client: Weak<Client>, fetch: Weak<fetch::Client>, operations: Address, update_policy: UpdatePolicy) -> Self {
|
pub fn new(client: Weak<Client>, fetch: Weak<fetch::Client>, operations: Address, update_policy: UpdatePolicy) -> Self {
|
||||||
let mut u = Updater {
|
let mut u = Updater {
|
||||||
@ -63,10 +70,11 @@ impl Updater {
|
|||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
operations: Operations::new(operations, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d))),
|
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,
|
update_policy: update_policy,
|
||||||
fetching: Mutex::new(false),
|
fetching: Mutex::new(None),
|
||||||
this: VersionInfo::this(),
|
this: VersionInfo::this(),
|
||||||
this_fork: None,
|
this_fork: None,
|
||||||
latest: None,
|
latest: None,
|
||||||
|
ready: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
u.this_fork = u.operations.release(CLIENT_ID, &u.this.hash.into()).ok()
|
u.this_fork = u.operations.release(CLIENT_ID, &u.this.hash.into()).ok()
|
||||||
@ -95,16 +103,26 @@ impl Updater {
|
|||||||
|
|
||||||
/// 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
|
||||||
/// `execute_upgrade` may be called.
|
/// `execute_upgrade` may be called.
|
||||||
pub fn upgrade_ready(&self) -> Option<VersionInfo> {
|
pub fn upgrade_ready(&self) -> Option<ReleaseInfo> {
|
||||||
unimplemented!()
|
self.ready.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actually upgrades the client. Assumes that the binary has been downloaded.
|
/// Actually upgrades the client. Assumes that the binary has been downloaded.
|
||||||
/// @returns `true` on success.
|
/// @returns `true` on success.
|
||||||
pub fn execute_upgrade(&mut self) -> bool {
|
pub fn execute_upgrade(&mut self) -> bool {
|
||||||
|
// TODO: link ~/.parity-updates/parity to self.ready
|
||||||
|
// TODO: restart parity.
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true iff the current version is capable of forming consensus.
|
||||||
|
pub fn consensus_capable(&self) -> bool {
|
||||||
|
/* if let Some(ref latest) = self.latest {
|
||||||
|
|
||||||
|
|
||||||
|
*/ unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Our version info.
|
/// Our version info.
|
||||||
pub fn version_info(&self) -> &VersionInfo { &self.this }
|
pub fn version_info(&self) -> &VersionInfo { &self.this }
|
||||||
|
|
||||||
@ -147,12 +165,37 @@ impl Updater {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_done(&self, _r: Result<PathBuf, fetch::Error>) {
|
fn fetch_done(&mut self, _r: Result<PathBuf, fetch::Error>) {
|
||||||
|
let fetched = self.fetching.lock().take().unwrap();
|
||||||
match _r {
|
match _r {
|
||||||
Ok(b) => info!("Fetched latest version OK: {}", b.display()),
|
Ok(b) => {
|
||||||
Err(e) => warn!("Unable to fetch latest version: {:?}", e),
|
info!("Fetched latest version ({}) OK to {}", fetched.version, b.display());
|
||||||
|
let mut dest = PathBuf::from(env::home_dir().unwrap().to_str().expect("env filesystem paths really should be valid; qed"));
|
||||||
|
dest.push(".parity-updates");
|
||||||
|
match fs::create_dir_all(&dest) {
|
||||||
|
Ok(_) => {
|
||||||
|
dest.push(format!("parity-{}-{:?}", fetched.version, fetched.version.hash));
|
||||||
|
match fs::copy(&b, &dest) {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Copied file to {}", dest.display());
|
||||||
|
let auto = match self.update_policy.filter {
|
||||||
|
UpdateFilter::All => true,
|
||||||
|
UpdateFilter::Critical if fetched.is_critical /* TODO: or is on a bad fork */ => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
self.ready = Some(fetched);
|
||||||
|
if auto {
|
||||||
|
self.execute_upgrade();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => warn!("Unable to copy update: {:?}", e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => warn!("Unable to create updates path: {:?}", e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => warn!("Unable to fetch update ({}): {:?}", fetched.version, e),
|
||||||
}
|
}
|
||||||
*self.fetching.lock() = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
@ -168,19 +211,21 @@ impl Updater {
|
|||||||
platform(),
|
platform(),
|
||||||
if let Some(ref b) = latest.track.binary {
|
if let Some(ref b) = latest.track.binary {
|
||||||
format!("{}", b)
|
format!("{}", b)
|
||||||
} else {
|
} else {
|
||||||
"unreleased".into()
|
"unreleased".into()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if let Some(b) = latest.track.binary {
|
if self.update_policy.enable_downloading && latest.track.version.hash != self.version_info().hash && self.ready.as_ref().map_or(true, |t| *t != latest.track) {
|
||||||
let mut fetching = self.fetching.lock();
|
if let Some(b) = latest.track.binary {
|
||||||
if !*fetching {
|
let mut fetching = self.fetching.lock();
|
||||||
info!("Attempting to get parity binary {}", b);
|
if fetching.is_none() {
|
||||||
let c = self.client.clone();
|
info!("Attempting to get parity binary {}", b);
|
||||||
let f = move |r: Result<PathBuf, fetch::Error>| if let Some(c) = c.upgrade() { c.updater().as_ref().expect("updater exists; updater only owned by client; qed").fetch_done(r); };
|
let c = self.client.clone();
|
||||||
if let Some(fetch) = self.fetch.clone().upgrade() {
|
let f = move |r: Result<PathBuf, fetch::Error>| if let Some(c) = c.upgrade() { c.updater().as_mut().expect("updater exists; updater only owned by client; qed").fetch_done(r); };
|
||||||
fetch.fetch(b, Box::new(f)).ok();
|
if let Some(fetch) = self.fetch.clone().upgrade() {
|
||||||
*fetching = true;
|
fetch.fetch(b, Box::new(f)).ok();
|
||||||
|
*fetching = Some(latest.track.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ Operating Options:
|
|||||||
--auto-update TRACK Set a release track to automatically update and
|
--auto-update TRACK Set a release track to automatically update and
|
||||||
install.
|
install.
|
||||||
all - All updates in the current release track.
|
all - All updates in the current release track.
|
||||||
patch - All updates of the current minor version.
|
|
||||||
critical - Only consensus/security updates.
|
critical - Only consensus/security updates.
|
||||||
none - No updates will be auto-installed.
|
none - No updates will be auto-installed.
|
||||||
(default: {flag_auto_update}).
|
(default: {flag_auto_update}).
|
||||||
|
@ -624,7 +624,6 @@ impl Configuration {
|
|||||||
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,
|
||||||
"patch" => UpdateFilter::Patch,
|
|
||||||
"all" => UpdateFilter::All,
|
"all" => UpdateFilter::All,
|
||||||
_ => return Err("Invalid value for `--auto-update`. See `--help` for more information.".into()),
|
_ => return Err("Invalid value for `--auto-update`. See `--help` for more information.".into()),
|
||||||
},
|
},
|
||||||
@ -985,13 +984,13 @@ mod tests {
|
|||||||
// when
|
// when
|
||||||
let conf0 = parse(&["parity"]);
|
let conf0 = parse(&["parity"]);
|
||||||
let conf1 = parse(&["parity", "--auto-update", "all"]);
|
let conf1 = parse(&["parity", "--auto-update", "all"]);
|
||||||
let conf2 = parse(&["parity", "--no-download", "--auto-update=patch"]);
|
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, 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, filter: UpdateFilter::All});
|
||||||
assert_eq!(conf2.update_policy().unwrap(), UpdatePolicy{enable_downloading: false, filter: UpdateFilter::Patch});
|
assert_eq!(conf2.update_policy().unwrap(), UpdatePolicy{enable_downloading: false, filter: UpdateFilter::All});
|
||||||
assert!(conf3.update_policy().is_err());
|
assert!(conf3.update_policy().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user