Initial structure for auto-updater.
- Add auto-gen'ed Operations and Registry ABIs. - Add Updater for managing updates. - Add fields in Client to enable update checking and registry.
This commit is contained in:
parent
28aabcdb6c
commit
401a4a37c1
@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::path::{Path};
|
use std::path::{Path};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -22,12 +24,11 @@ use std::time::{Instant};
|
|||||||
use time::precise_time_ns;
|
use time::precise_time_ns;
|
||||||
|
|
||||||
// util
|
// util
|
||||||
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, ToPretty};
|
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, MutexGuard, Hashable};
|
||||||
use util::{journaldb, TrieFactory, Trie};
|
use util::{journaldb, TrieFactory, Trie};
|
||||||
use util::trie::TrieSpec;
|
use util::trie::TrieSpec;
|
||||||
use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
||||||
use util::kvdb::*;
|
use util::kvdb::*;
|
||||||
use util::misc::code_hash;
|
|
||||||
|
|
||||||
// other
|
// other
|
||||||
use io::*;
|
use io::*;
|
||||||
@ -69,7 +70,8 @@ use factory::Factories;
|
|||||||
use rlp::{decode, View, UntrustedRlp};
|
use rlp::{decode, View, UntrustedRlp};
|
||||||
use state_db::StateDB;
|
use state_db::StateDB;
|
||||||
use rand::OsRng;
|
use rand::OsRng;
|
||||||
use ethabi::{Interface, Contract, Token};
|
use client::updater::Updater;
|
||||||
|
use client::registry::Registry;
|
||||||
|
|
||||||
// re-export
|
// re-export
|
||||||
pub use types::blockchain_info::BlockChainInfo;
|
pub use types::blockchain_info::BlockChainInfo;
|
||||||
@ -140,6 +142,7 @@ pub struct Client {
|
|||||||
panic_handler: Arc<PanicHandler>,
|
panic_handler: Arc<PanicHandler>,
|
||||||
verifier: Box<Verifier>,
|
verifier: Box<Verifier>,
|
||||||
miner: Arc<Miner>,
|
miner: Arc<Miner>,
|
||||||
|
updater: Mutex<Option<Updater>>,
|
||||||
sleep_state: Mutex<SleepState>,
|
sleep_state: Mutex<SleepState>,
|
||||||
liveness: AtomicBool,
|
liveness: AtomicBool,
|
||||||
io_channel: Mutex<IoChannel<ClientIoMessage>>,
|
io_channel: Mutex<IoChannel<ClientIoMessage>>,
|
||||||
@ -150,6 +153,7 @@ pub struct Client {
|
|||||||
history: u64,
|
history: u64,
|
||||||
rng: Mutex<OsRng>,
|
rng: Mutex<OsRng>,
|
||||||
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
||||||
|
registrar: Mutex<Option<Registry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -222,7 +226,7 @@ impl Client {
|
|||||||
accountdb: Default::default(),
|
accountdb: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = Client {
|
let client = Arc::new(Client {
|
||||||
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()),
|
||||||
@ -239,6 +243,7 @@ impl Client {
|
|||||||
import_lock: Mutex::new(()),
|
import_lock: Mutex::new(()),
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
miner: miner,
|
miner: miner,
|
||||||
|
updater: Mutex::new(None),
|
||||||
io_channel: Mutex::new(message_channel),
|
io_channel: Mutex::new(message_channel),
|
||||||
notify: RwLock::new(Vec::new()),
|
notify: RwLock::new(Vec::new()),
|
||||||
queue_transactions: AtomicUsize::new(0),
|
queue_transactions: AtomicUsize::new(0),
|
||||||
@ -247,8 +252,19 @@ impl Client {
|
|||||||
history: history,
|
history: history,
|
||||||
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
|
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
|
||||||
on_mode_change: Mutex::new(None),
|
on_mode_change: Mutex::new(None),
|
||||||
};
|
registrar: Mutex::new(None),
|
||||||
Ok(Arc::new(client))
|
});
|
||||||
|
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
||||||
|
let weak = Arc::downgrade(&client);
|
||||||
|
let registrar = Registry::new(reg_addr, move |a, d| weak.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d)));
|
||||||
|
if let Ok(operations) = registrar.get_address(&(&b"operations"[..]).sha3(), "A") {
|
||||||
|
if !operations.is_zero() {
|
||||||
|
*client.updater.lock() = Some(Updater::new(Arc::downgrade(&client), operations));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*client.registrar.lock() = Some(registrar);
|
||||||
|
}
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an actor to be notified on certain events
|
/// Adds an actor to be notified on certain events
|
||||||
@ -264,6 +280,11 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the Registry object - useful for looking up names.
|
||||||
|
pub fn registrar(&self) -> MutexGuard<Option<Registry>> {
|
||||||
|
self.registrar.lock()
|
||||||
|
}
|
||||||
|
|
||||||
/// Register an action to be done if a mode change happens.
|
/// Register an action to be done if a mode change happens.
|
||||||
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
||||||
*self.on_mode_change.lock() = Some(Box::new(f));
|
*self.on_mode_change.lock() = Some(Box::new(f));
|
||||||
@ -644,7 +665,9 @@ impl Client {
|
|||||||
pub fn tick(&self) {
|
pub fn tick(&self) {
|
||||||
self.check_garbage();
|
self.check_garbage();
|
||||||
self.check_snooze();
|
self.check_snooze();
|
||||||
self.check_updates();
|
if let Some(ref mut updater) = *self.updater.lock() {
|
||||||
|
updater.tick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_garbage(&self) {
|
fn check_garbage(&self) {
|
||||||
@ -687,7 +710,8 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
|
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||||
|
pub fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||||
let from = Address::default();
|
let from = Address::default();
|
||||||
let transaction = Transaction {
|
let transaction = Transaction {
|
||||||
nonce: self.latest_nonce(&from),
|
nonce: self.latest_nonce(&from),
|
||||||
@ -705,39 +729,6 @@ impl Client {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_updates(&self) {
|
|
||||||
let operations_json = Interface::load(include_bytes!("../../res/Operations.json")).expect("Operations.json is valid ABI");
|
|
||||||
let operations = Contract::new(operations_json);
|
|
||||||
|
|
||||||
fn as_string<T: fmt::Debug>(e: T) -> String {
|
|
||||||
format!("{:?}", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = || {
|
|
||||||
let is_latest = try!(operations.function("isLatest".into()).map_err(as_string));
|
|
||||||
let params = try!(is_latest.encode_call(
|
|
||||||
vec![Token::FixedBytes(b"par"[..].to_owned()), Token::Address(code_hash().0)]
|
|
||||||
).map_err(as_string));
|
|
||||||
println!("params: {}", params.pretty());
|
|
||||||
let output = try!(self.call_contract("0x4c1783B4FfB1A99eFC4cda632aA990F5138b26f1".into(), params));
|
|
||||||
let result = try!(is_latest.decode_output(output).map_err(as_string));
|
|
||||||
|
|
||||||
match result.get(0) {
|
|
||||||
Some(&Token::Bool(answer)) => Ok(answer),
|
|
||||||
e => Err(format!("Invalid result: {:?}", e)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match res() {
|
|
||||||
Ok(res) => {
|
|
||||||
info!("isLatest returned {}", res);
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
warn!(target: "dapps", "Error while calling Operations.isLatest: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Look up the block number for the given block ID.
|
/// Look up the block number for the given block ID.
|
||||||
pub fn block_number(&self, id: BlockID) -> Option<BlockNumber> {
|
pub fn block_number(&self, id: BlockID) -> Option<BlockNumber> {
|
||||||
match id {
|
match id {
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use trace::Error as TraceError;
|
use trace::Error as TraceError;
|
||||||
use util::UtilError;
|
use util::UtilError;
|
||||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||||
|
@ -16,11 +16,14 @@
|
|||||||
|
|
||||||
//! Blockchain database client.
|
//! Blockchain database client.
|
||||||
|
|
||||||
|
mod operations;
|
||||||
|
mod registry;
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod test_client;
|
mod test_client;
|
||||||
mod trace;
|
mod trace;
|
||||||
mod client;
|
mod client;
|
||||||
|
mod updater;
|
||||||
|
|
||||||
pub use self::client::*;
|
pub use self::client::*;
|
||||||
pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType};
|
pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType};
|
||||||
|
336
ethcore/src/client/operations.rs
Normal file
336
ethcore/src/client/operations.rs
Normal file
File diff suppressed because one or more lines are too long
264
ethcore/src/client/registry.rs
Normal file
264
ethcore/src/client/registry.rs
Normal file
File diff suppressed because one or more lines are too long
45
ethcore/src/client/updater.rs
Normal file
45
ethcore/src/client/updater.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
||||||
|
use std::sync::Weak;
|
||||||
|
use util::misc::code_hash;
|
||||||
|
use util::Address;
|
||||||
|
use client::operations::Operations;
|
||||||
|
use client::client::Client;
|
||||||
|
|
||||||
|
pub struct Updater {
|
||||||
|
operations: Operations,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Updater {
|
||||||
|
pub fn new(client: Weak<Client>, operations: Address) -> Self {
|
||||||
|
Updater {
|
||||||
|
operations: Operations::new(operations, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(&mut self) {
|
||||||
|
match self.operations.is_latest("par", &code_hash().into()) {
|
||||||
|
Ok(res) => {
|
||||||
|
info!("isLatest returned {}", res);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warn!(target: "dapps", "Error while calling Operations.isLatest: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user