Merge branch 'master' of github.com:ethcore/parity into tx-block

This commit is contained in:
arkpar
2016-12-16 13:36:07 +01:00
125 changed files with 4066 additions and 694 deletions

View File

@@ -13,7 +13,9 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
use std::str::FromStr;
use std::sync::{Arc, Weak};
use std::path::{Path};
use std::fmt;
@@ -22,7 +24,7 @@ use std::time::{Instant};
use time::precise_time_ns;
// util
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, Hashable};
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, MutexGuard, Hashable};
use util::{journaldb, TrieFactory, Trie};
use util::{U256, H256, Address, H2048, Uint, FixedHash};
use util::trie::TrieSpec;
@@ -42,7 +44,7 @@ use env_info::LastHashes;
use verification;
use verification::{PreverifiedBlock, Verifier};
use block::*;
use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction, Action};
use transaction::{LocalizedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
use blockchain::extras::TransactionAddress;
use types::filter::Filter;
use types::mode::Mode as IpcMode;
@@ -68,6 +70,7 @@ use factory::Factories;
use rlp::{decode, View, UntrustedRlp};
use state_db::StateDB;
use rand::OsRng;
use client::registry::Registry;
// re-export
pub use types::blockchain_info::BlockChainInfo;
@@ -124,6 +127,7 @@ impl SleepState {
/// 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.
pub struct Client {
enabled: AtomicBool,
mode: Mutex<Mode>,
chain: RwLock<Arc<BlockChain>>,
tracedb: RwLock<TraceDB<BlockChain>>,
@@ -148,6 +152,7 @@ pub struct Client {
history: u64,
rng: Mutex<OsRng>,
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
registrar: Mutex<Option<Registry>>,
}
impl Client {
@@ -160,6 +165,7 @@ impl Client {
message_channel: IoChannel<ClientIoMessage>,
db_config: &DatabaseConfig,
) -> Result<Arc<Client>, ClientError> {
let path = path.to_path_buf();
let gb = spec.genesis_block();
@@ -221,7 +227,8 @@ impl Client {
accountdb: Default::default(),
};
let client = Client {
let client = Arc::new(Client {
enabled: AtomicBool::new(true),
sleep_state: Mutex::new(SleepState::new(awake)),
liveness: AtomicBool::new(awake),
mode: Mutex::new(config.mode.clone()),
@@ -246,8 +253,15 @@ impl Client {
history: history,
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
on_mode_change: Mutex::new(None),
};
Ok(Arc::new(client))
registrar: Mutex::new(None),
});
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
trace!(target: "client", "Found registrar at {}", reg_addr);
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)));
*client.registrar.lock() = Some(registrar);
}
Ok(client)
}
/// Adds an actor to be notified on certain events
@@ -268,6 +282,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.
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
*self.on_mode_change.lock() = Some(Box::new(f));
@@ -395,6 +414,12 @@ impl Client {
/// 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 {
// 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 (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
@@ -663,10 +688,17 @@ impl Client {
/// Tick the client.
// TODO: manage by real events.
pub fn tick(&self) {
self.check_garbage();
self.check_snooze();
}
fn check_garbage(&self) {
self.chain.read().collect_garbage();
self.block_queue.collect_garbage();
self.tracedb.read().collect_garbage();
}
fn check_snooze(&self) {
let mode = self.mode.lock().clone();
match mode {
Mode::Dark(timeout) => {
@@ -700,16 +732,6 @@ impl Client {
}
}
/// Look up the block number for the given block ID.
pub fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
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<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> {
@@ -908,8 +930,17 @@ impl BlockChainClient for Client {
r
}
fn disable(&self) {
self.set_mode(IpcMode::Off);
self.enabled.store(false, AtomicOrdering::Relaxed);
self.clear_queue();
}
fn set_mode(&self, new_mode: IpcMode) {
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
if !self.enabled.load(AtomicOrdering::Relaxed) {
return;
}
{
let mut mode = self.mode.lock();
*mode = new_mode.clone().into();
@@ -935,6 +966,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<BlockNumber> {
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<Bytes> {
let chain = self.chain.read();
Self::block_hash(&chain, id).and_then(|hash| chain.block_body(&hash))
@@ -1331,6 +1371,34 @@ impl BlockChainClient for Client {
earliest_state: self.state_db.lock().journal_db().earliest_era().unwrap_or(0),
}
}
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
let from = Address::default();
let transaction = Transaction {
nonce: self.latest_nonce(&from),
action: Action::Call(address),
gas: U256::from(50_000_000),
gas_price: U256::default(),
value: U256::default(),
data: data,
}.fake_sign(from);
self.call(&transaction, BlockId::Latest, Default::default())
.map_err(|e| format!("{:?}", e))
.map(|executed| {
executed.output
})
}
fn registrar_address(&self) -> Option<Address> {
self.registrar.lock().as_ref().map(|r| r.address.clone())
}
fn registry_address(&self, name: String) -> Option<Address> {
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 {

View File

@@ -1,3 +1,19 @@
// Copyright 2015, 2016 Parity Technologies (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 util::UtilError;
use std::fmt::{Display, Formatter, Error as FmtError};

View File

@@ -16,6 +16,7 @@
//! Blockchain database client.
mod registry;
mod config;
mod error;
mod test_client;

File diff suppressed because one or more lines are too long

View File

@@ -488,6 +488,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<BlockNumber> {
unimplemented!()
}
fn block_body(&self, id: BlockId) -> Option<Bytes> {
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| {
let mut stream = RlpStream::new_list(2);
@@ -694,10 +698,18 @@ impl BlockChainClient for TestBlockChainClient {
fn set_mode(&self, _: Mode) { unimplemented!(); }
fn disable(&self) { unimplemented!(); }
fn pruning_info(&self) -> PruningInfo {
PruningInfo {
earliest_chain: 1,
earliest_state: 1,
}
}
fn call_contract(&self, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
fn registrar_address(&self) -> Option<Address> { None }
fn registry_address(&self, _name: String) -> Option<Address> { None }
}

View File

@@ -52,6 +52,9 @@ pub trait BlockChainClient : Sync + Send {
/// Get raw block header data by block id.
fn block_header(&self, id: BlockId) -> Option<Bytes>;
/// Look up the block number for the given block ID.
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
/// 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<Bytes>;
@@ -255,6 +258,10 @@ pub trait BlockChainClient : Sync + Send {
/// Set the 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`.
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>>;
@@ -263,6 +270,15 @@ pub trait BlockChainClient : Sync + Send {
/// Returns information about pruning/data availability.
fn pruning_info(&self) -> PruningInfo;
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String>;
/// Get the address of the registry itself.
fn registrar_address(&self) -> Option<Address>;
/// Get the address of a particular blockchain service, if available.
fn registry_address(&self, name: String) -> Option<Address>;
}
impl IpcConfig for BlockChainClient { }