Merge branch 'master' into secret-store

This commit is contained in:
Nikolay Volf 2016-02-14 16:01:29 +03:00
commit ae5ec6bad9
39 changed files with 362 additions and 305 deletions

12
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,12 @@
# Contributing to Parity
## License
By contributing to Parity, you agree that your contributions will be
licensed under the [BSD License](LICENSE).
At the top of every source code file you alter, after the initial
licence section, please append a second section that reads:
Portions contributed by YOUR NAME are hereby placed under the BSD licence.

View File

@ -12,7 +12,7 @@ rustc-serialize = "0.3"
docopt = "0.6"
docopt_macros = "0.6"
ctrlc = { git = "https://github.com/tomusdrw/rust-ctrlc.git" }
clippy = "0.0.37"
clippy = "0.0.41"
ethcore-util = { path = "util" }
ethcore = { path = "ethcore" }
ethsync = { path = "sync" }

View File

@ -18,7 +18,7 @@ ethcore-util = { path = "../util" }
evmjit = { path = "../evmjit", optional = true }
ethash = { path = "../ethash" }
num_cpus = "0.2"
clippy = "0.0.37"
clippy = "0.0.41"
crossbeam = "0.1.5"
lazy_static = "0.1"

View File

@ -3,7 +3,7 @@
"engineName": "Ethash",
"params": {
"accountStartNonce": "0x00",
"frontierCompatibilityModeLimit": "0xf4240",
"frontierCompatibilityModeLimit": "0xf4240fff",
"maximumExtraDataSize": "0x20",
"tieBreakingGas": false,
"minGasLimit": "0x1388",

View File

@ -3,7 +3,7 @@
"engineName": "Ethash",
"params": {
"accountStartNonce": "0x00",
"frontierCompatibilityModeLimit": "0xf4240",
"frontierCompatibilityModeLimit": "0xf4240fff",
"maximumExtraDataSize": "0x20",
"tieBreakingGas": false,
"minGasLimit": "0x1388",

View File

@ -72,14 +72,14 @@ impl AccountDiff {
pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option<AccountDiff> {
match (pre, post) {
(None, Some(x)) => Some(AccountDiff {
balance: Diff::Born(x.balance.clone()),
nonce: Diff::Born(x.nonce.clone()),
balance: Diff::Born(x.balance),
nonce: Diff::Born(x.nonce),
code: Diff::Born(x.code.clone()),
storage: x.storage.iter().map(|(k, v)| (k.clone(), Diff::Born(v.clone()))).collect(),
}),
(Some(x), None) => Some(AccountDiff {
balance: Diff::Died(x.balance.clone()),
nonce: Diff::Died(x.nonce.clone()),
balance: Diff::Died(x.balance),
nonce: Diff::Died(x.nonce),
code: Diff::Died(x.code.clone()),
storage: x.storage.iter().map(|(k, v)| (k.clone(), Diff::Died(v.clone()))).collect(),
}),
@ -88,8 +88,8 @@ impl AccountDiff {
.filter(|k| pre.storage.get(k).unwrap_or(&H256::new()) != post.storage.get(k).unwrap_or(&H256::new()))
.collect();
let r = AccountDiff {
balance: Diff::new(pre.balance.clone(), post.balance.clone()),
nonce: Diff::new(pre.nonce.clone(), post.nonce.clone()),
balance: Diff::new(pre.balance, post.balance),
nonce: Diff::new(pre.nonce, post.nonce),
code: Diff::new(pre.code.clone(), post.code.clone()),
storage: storage.into_iter().map(|k|
(k.clone(), Diff::new(

View File

@ -23,24 +23,6 @@ use extras::*;
use transaction::*;
use views::*;
/// Uniquely identifies block.
pub enum BlockId {
/// Block's sha3.
/// Querying by hash is always faster.
Hash(H256),
/// Block number within canon blockchain.
Number(BlockNumber)
}
/// Uniquely identifies transaction.
pub enum TransactionId {
/// Transaction's sha3.
Hash(H256),
/// Block id and transaction index within this block.
/// Querying by block position is always faster.
Location(BlockId, usize)
}
/// Represents a tree route between `from` block and `to` block:
pub struct TreeRoute {
/// A vector of hashes of all blocks, ordered from `from` to `to`.
@ -129,18 +111,8 @@ pub trait BlockProvider {
}
/// Get transaction with given transaction hash.
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> {
match id {
TransactionId::Hash(ref hash) => self.transaction_address(hash),
TransactionId::Location(BlockId::Hash(hash), index) => Some(TransactionAddress {
block_hash: hash,
index: index
}),
TransactionId::Location(BlockId::Number(number), index) => self.block_hash(number).map(|hash| TransactionAddress {
block_hash: hash,
index: index
})
}.and_then(|address| self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index)))
fn transaction(&self, address: &TransactionAddress) -> Option<LocalizedTransaction> {
self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index))
}
/// Get a list of transactions for a given block.
@ -887,7 +859,7 @@ mod tests {
let transactions = bc.transactions(&b1_hash).unwrap();
assert_eq!(transactions.len(), 7);
for t in transactions {
assert_eq!(bc.transaction(TransactionId::Hash(t.hash())).unwrap(), t);
assert_eq!(bc.transaction(&bc.transaction_address(&t.hash()).unwrap()).unwrap(), t);
}
}
}

View File

@ -19,7 +19,7 @@
use util::*;
use util::panics::*;
use rocksdb::{Options, DB, DBCompactionStyle};
use blockchain::{BlockChain, BlockProvider, CacheSize, TransactionId};
use blockchain::{BlockChain, BlockProvider, CacheSize};
use views::BlockView;
use error::*;
use header::BlockNumber;
@ -33,8 +33,33 @@ use env_info::LastHashes;
use verification::*;
use block::*;
use transaction::LocalizedTransaction;
use extras::TransactionAddress;
pub use blockchain::TreeRoute;
/// Uniquely identifies block.
#[derive(Debug, PartialEq, Clone)]
pub enum BlockId {
/// Block's sha3.
/// Querying by hash is always faster.
Hash(H256),
/// Block number within canon blockchain.
Number(BlockNumber),
/// Earliest block (genesis).
Earliest,
/// Latest mined block.
Latest
}
/// Uniquely identifies transaction.
#[derive(Debug, PartialEq, Clone)]
pub enum TransactionId {
/// Transaction's sha3.
Hash(H256),
/// Block id and transaction index within this block.
/// Querying by block position is always faster.
Location(BlockId, usize)
}
/// General block status
#[derive(Debug, Eq, PartialEq)]
pub enum BlockStatus {
@ -71,41 +96,25 @@ impl fmt::Display for BlockChainInfo {
/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send {
/// Get raw block header data by block header hash.
fn block_header(&self, hash: &H256) -> Option<Bytes>;
/// Get raw block header data by block id.
fn block_header(&self, id: BlockId) -> Option<Bytes>;
/// Get raw block body data by block header hash.
/// Get raw block body data by block id.
/// Block body is an RLP list of two items: uncles and transactions.
fn block_body(&self, hash: &H256) -> Option<Bytes>;
fn block_body(&self, id: BlockId) -> Option<Bytes>;
/// Get raw block data by block header hash.
fn block(&self, hash: &H256) -> Option<Bytes>;
fn block(&self, id: BlockId) -> Option<Bytes>;
/// Get block status by block header hash.
fn block_status(&self, hash: &H256) -> BlockStatus;
fn block_status(&self, id: BlockId) -> BlockStatus;
/// Get block total difficulty.
fn block_total_difficulty(&self, hash: &H256) -> Option<U256>;
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
/// Get address code.
fn code(&self, address: &Address) -> Option<Bytes>;
/// Get raw block header data by block number.
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get raw block body data by block number.
/// Block body is an RLP list of two items: uncles and transactions.
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get raw block data by block number.
fn block_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get block status by block number.
fn block_status_at(&self, n: BlockNumber) -> BlockStatus;
/// Get block total difficulty.
fn block_total_difficulty_at(&self, n: BlockNumber) -> Option<U256>;
/// Get transaction with given hash.
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
@ -133,7 +142,7 @@ pub trait BlockChainClient : Sync + Send {
/// Get the best block header.
fn best_block_header(&self) -> Bytes {
self.block_header(&self.chain_info().best_block_hash).unwrap()
self.block_header(BlockId::Hash(self.chain_info().best_block_hash)).unwrap()
}
}
@ -170,7 +179,7 @@ pub struct Client {
}
const HISTORY: u64 = 1000;
const CLIENT_DB_VER_STR: &'static str = "2.0";
const CLIENT_DB_VER_STR: &'static str = "2.1";
impl Client {
/// Create a new client with given spec and DB path.
@ -307,12 +316,11 @@ impl Client {
self.report.write().unwrap().accrue_block(&block);
trace!(target: "client", "Imported #{} ({})", header.number(), header.hash());
ret += 1;
if self.block_queue.read().unwrap().queue_info().is_empty() {
io.send(NetworkIoMessage::User(SyncMessage::BlockVerified)).unwrap();
}
}
self.block_queue.write().unwrap().mark_as_good(&good_blocks);
if !good_blocks.is_empty() && self.block_queue.read().unwrap().queue_info().is_empty() {
io.send(NetworkIoMessage::User(SyncMessage::BlockVerified)).unwrap();
}
ret
}
@ -340,68 +348,70 @@ impl Client {
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
self.chain.write().unwrap().configure_cache(pref_cache_size, max_cache_size);
}
fn block_hash(chain: &BlockChain, id: BlockId) -> Option<H256> {
match id {
BlockId::Hash(hash) => Some(hash),
BlockId::Number(number) => chain.block_hash(number),
BlockId::Earliest => chain.block_hash(0),
BlockId::Latest => Some(chain.best_block_hash())
}
}
}
impl BlockChainClient for Client {
fn block_header(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().unwrap().block(hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec())
fn block_header(&self, id: BlockId) -> Option<Bytes> {
let chain = self.chain.read().unwrap();
Self::block_hash(&chain, id).and_then(|hash| chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec()))
}
fn block_body(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().unwrap().block(hash).map(|bytes| {
let rlp = Rlp::new(&bytes);
let mut body = RlpStream::new();
body.append_raw(rlp.at(1).as_raw(), 1);
body.append_raw(rlp.at(2).as_raw(), 1);
body.out()
fn block_body(&self, id: BlockId) -> Option<Bytes> {
let chain = self.chain.read().unwrap();
Self::block_hash(&chain, id).and_then(|hash| {
chain.block(&hash).map(|bytes| {
let rlp = Rlp::new(&bytes);
let mut body = RlpStream::new_list(2);
body.append_raw(rlp.at(1).as_raw(), 1);
body.append_raw(rlp.at(2).as_raw(), 1);
body.out()
})
})
}
fn block(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().unwrap().block(hash)
fn block(&self, id: BlockId) -> Option<Bytes> {
let chain = self.chain.read().unwrap();
Self::block_hash(&chain, id).and_then(|hash| {
chain.block(&hash)
})
}
fn block_status(&self, hash: &H256) -> BlockStatus {
if self.chain.read().unwrap().is_known(&hash) {
BlockStatus::InChain
} else {
self.block_queue.read().unwrap().block_status(hash)
fn block_status(&self, id: BlockId) -> BlockStatus {
let chain = self.chain.read().unwrap();
match Self::block_hash(&chain, id) {
Some(ref hash) if chain.is_known(hash) => BlockStatus::InChain,
Some(hash) => self.block_queue.read().unwrap().block_status(&hash),
None => BlockStatus::Unknown
}
}
fn block_total_difficulty(&self, hash: &H256) -> Option<U256> {
self.chain.read().unwrap().block_details(hash).map(|d| d.total_difficulty)
fn block_total_difficulty(&self, id: BlockId) -> Option<U256> {
let chain = self.chain.read().unwrap();
Self::block_hash(&chain, id).and_then(|hash| chain.block_details(&hash)).map(|d| d.total_difficulty)
}
fn code(&self, address: &Address) -> Option<Bytes> {
self.state().code(address)
}
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_header(&h))
}
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_body(&h))
}
fn block_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block(&h))
}
fn block_status_at(&self, n: BlockNumber) -> BlockStatus {
match self.chain.read().unwrap().block_hash(n) {
Some(h) => self.block_status(&h),
None => BlockStatus::Unknown
}
}
fn block_total_difficulty_at(&self, n: BlockNumber) -> Option<U256> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_total_difficulty(&h))
}
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> {
self.chain.read().unwrap().transaction(id)
let chain = self.chain.read().unwrap();
match id {
TransactionId::Hash(ref hash) => chain.transaction_address(hash),
TransactionId::Location(id, index) => Self::block_hash(&chain, id).map(|hash| TransactionAddress {
block_hash: hash,
index: index
})
}.and_then(|address| chain.transaction(&address))
}
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
@ -421,7 +431,7 @@ impl BlockChainClient for Client {
if self.chain.read().unwrap().is_known(&header.hash()) {
return Err(ImportError::AlreadyInChain);
}
if self.block_status(&header.parent_hash) == BlockStatus::Unknown {
if self.block_status(BlockId::Hash(header.parent_hash)) == BlockStatus::Unknown {
return Err(ImportError::UnknownParent);
}
self.block_queue.write().unwrap().import_block(bytes)

View File

@ -274,7 +274,7 @@ mod tests {
use block::*;
use engine::*;
use tests::helpers::*;
use super::*;
use super::{Ethash};
use super::super::new_morden;
#[test]

View File

@ -24,7 +24,7 @@ pub mod ethash;
/// Export the denominations module.
pub mod denominations;
pub use self::ethash::*;
pub use self::ethash::{Ethash};
pub use self::denominations::*;
use super::spec::*;

View File

@ -391,10 +391,7 @@ impl Interpreter {
instructions::SLOAD => {
InstructionCost::Gas(U256::from(schedule.sload_gas))
},
instructions::MSTORE => {
InstructionCost::GasMem(default_gas, try!(self.mem_needed_const(stack.peek(0), 32)))
},
instructions::MLOAD => {
instructions::MSTORE | instructions::MLOAD => {
InstructionCost::GasMem(default_gas, try!(self.mem_needed_const(stack.peek(0), 32)))
},
instructions::MSTORE8 => {
@ -736,8 +733,7 @@ impl Interpreter {
},
instructions::CALLVALUE => {
stack.push(match params.value {
ActionValue::Transfer(val) => val,
ActionValue::Apparent(val) => val,
ActionValue::Transfer(val) | ActionValue::Apparent(val) => val
});
},
instructions::CALLDATALOAD => {

View File

@ -84,7 +84,7 @@ impl Ext for FakeExt {
}
fn balance(&self, address: &Address) -> U256 {
self.balances.get(address).unwrap().clone()
*self.balances.get(address).unwrap()
}
fn blockhash(&self, number: &U256) -> H256 {
@ -94,10 +94,10 @@ impl Ext for FakeExt {
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::CREATE,
gas: gas.clone(),
gas: *gas,
sender_address: None,
receive_address: None,
value: Some(value.clone()),
value: Some(*value),
data: code.to_vec(),
code_address: None
});
@ -115,14 +115,14 @@ impl Ext for FakeExt {
self.calls.insert(FakeCall {
call_type: FakeCallType::CALL,
gas: gas.clone(),
gas: *gas,
sender_address: Some(sender_address.clone()),
receive_address: Some(receive_address.clone()),
value: value,
data: data.to_vec(),
code_address: Some(code_address.clone())
});
MessageCallResult::Success(gas.clone())
MessageCallResult::Success(*gas)
}
fn extcode(&self, address: &Address) -> Bytes {
@ -898,7 +898,7 @@ fn test_calls(factory: super::Factory) {
let mut ext = FakeExt::new();
ext.balances = {
let mut s = HashMap::new();
s.insert(params.address.clone(), params.gas.clone());
s.insert(params.address.clone(), params.gas);
s
};

View File

@ -45,10 +45,9 @@ impl OriginInfo {
OriginInfo {
address: params.address.clone(),
origin: params.origin.clone(),
gas_price: params.gas_price.clone(),
gas_price: params.gas_price,
value: match params.value {
ActionValue::Transfer(val) => val,
ActionValue::Apparent(val) => val,
ActionValue::Transfer(val) | ActionValue::Apparent(val) => val
}
}
}
@ -133,8 +132,8 @@ impl<'a> Ext for Externalities<'a> {
sender: self.origin_info.address.clone(),
origin: self.origin_info.origin.clone(),
gas: *gas,
gas_price: self.origin_info.gas_price.clone(),
value: ActionValue::Transfer(value.clone()),
gas_price: self.origin_info.gas_price,
value: ActionValue::Transfer(*value),
code: Some(code.to_vec()),
data: None,
};
@ -164,11 +163,11 @@ impl<'a> Ext for Externalities<'a> {
let mut params = ActionParams {
sender: sender_address.clone(),
address: receive_address.clone(),
value: ActionValue::Apparent(self.origin_info.value.clone()),
value: ActionValue::Apparent(self.origin_info.value),
code_address: code_address.clone(),
origin: self.origin_info.origin.clone(),
gas: *gas,
gas_price: self.origin_info.gas_price.clone(),
gas_price: self.origin_info.gas_price,
code: self.state.code(code_address),
data: Some(data.to_vec()),
};

View File

@ -115,7 +115,7 @@ declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"}
declare_test!{StateTests_stSpecialTest, "StateTests/stSpecialTest"}
declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"}
declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"}
declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"}
//declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"}
declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"}

View File

@ -43,8 +43,8 @@ impl PodAccount {
/// NOTE: This will silently fail unless the account is fully cached.
pub fn from_account(acc: &Account) -> PodAccount {
PodAccount {
balance: acc.balance().clone(),
nonce: acc.nonce().clone(),
balance: *acc.balance(),
nonce: *acc.nonce(),
storage: acc.storage_overlay().iter().fold(BTreeMap::new(), |mut m, (k, &(_, ref v))| {m.insert(k.clone(), v.clone()); m}),
code: acc.code().unwrap().to_vec(),
}

View File

@ -20,7 +20,6 @@ use util::*;
use util::panics::*;
use spec::Spec;
use error::*;
use std::env;
use client::Client;
/// Message type for external and internal events
@ -44,16 +43,14 @@ pub struct ClientService {
impl ClientService {
/// Start the service in a separate thread.
pub fn start(spec: Spec, net_config: NetworkConfiguration) -> Result<ClientService, Error> {
pub fn start(spec: Spec, net_config: NetworkConfiguration, db_path: &Path) -> Result<ClientService, Error> {
let panic_handler = PanicHandler::new_in_arc();
let mut net_service = try!(NetworkService::start(net_config));
panic_handler.forward_from(&net_service);
info!("Starting {}", net_service.host_info());
info!("Configured for {} using {} engine", spec.name, spec.engine_name);
let mut dir = env::home_dir().unwrap();
dir.push(".parity");
let client = try!(Client::new(spec, &dir, net_service.io().channel()));
let client = try!(Client::new(spec, db_path, net_service.io().channel()));
panic_handler.forward_from(client.deref());
let client_io = Arc::new(ClientIoHandler {
client: client.clone()
@ -136,7 +133,8 @@ mod tests {
#[test]
fn it_can_be_started() {
let spec = get_test_spec();
let service = ClientService::start(spec, NetworkConfiguration::new());
let temp_path = RandomTempPath::new();
let service = ClientService::start(spec, NetworkConfiguration::new(), &temp_path.as_path());
assert!(service.is_ok());
}
}

View File

@ -153,12 +153,12 @@ impl State {
/// Get the balance of account `a`.
pub fn balance(&self, a: &Address) -> U256 {
self.get(a, false).as_ref().map_or(U256::zero(), |account| account.balance().clone())
self.get(a, false).as_ref().map_or(U256::zero(), |account| *account.balance())
}
/// Get the nonce of account `a`.
pub fn nonce(&self, a: &Address) -> U256 {
self.get(a, false).as_ref().map_or(U256::zero(), |account| account.nonce().clone())
self.get(a, false).as_ref().map_or(U256::zero(), |account| *account.nonce())
}
/// Mutate storage of account `address` so that it is `value` for `key`.

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use client::{BlockChainClient,Client};
use client::{BlockChainClient, Client, BlockId};
use tests::helpers::*;
use common::*;
@ -44,7 +44,7 @@ fn imports_good_block() {
client.flush_queue();
client.import_verified_blocks(&IoChannel::disconnected());
let block = client.block_header_at(1).unwrap();
let block = client.block_header(BlockId::Number(1)).unwrap();
assert!(!block.is_empty());
}
@ -53,7 +53,7 @@ fn query_none_block() {
let dir = RandomTempPath::new();
let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
let non_existant = client.block_header_at(188);
let non_existant = client.block_header(BlockId::Number(188));
assert!(non_existant.is_none());
}
@ -61,7 +61,7 @@ fn query_none_block() {
fn query_bad_block() {
let client_result = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]);
let client = client_result.reference();
let bad_block:Option<Bytes> = client.block_header_at(1);
let bad_block:Option<Bytes> = client.block_header(BlockId::Number(1));
assert!(bad_block.is_none());
}
@ -76,11 +76,24 @@ fn returns_chain_info() {
assert_eq!(info.best_block_hash, block.header().hash());
}
#[test]
fn returns_block_body() {
let dummy_block = get_good_dummy_block();
let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]);
let client = client_result.reference();
let block = BlockView::new(&dummy_block);
let body = client.block_body(BlockId::Hash(block.header().hash())).unwrap();
let body = Rlp::new(&body);
assert_eq!(body.item_count(), 2);
assert_eq!(body.at(0).as_raw()[..], block.rlp().at(1).as_raw()[..]);
assert_eq!(body.at(1).as_raw()[..], block.rlp().at(2).as_raw()[..]);
}
#[test]
fn imports_block_sequence() {
let client_result = generate_dummy_client(6);
let client = client_result.reference();
let block = client.block_header_at(5).unwrap();
let block = client.block_header(BlockId::Number(5)).unwrap();
assert!(!block.is_empty());
}

View File

@ -570,7 +570,7 @@ function run_installer()
sudo apt-add-repository -y ppa:ethcore/ethcore
sudo apt-get -f -y install
sudo apt-get update -qq
sudo apt-get install -qq -y librocksdb-dev
sudo apt-get install -qq -y librocksdb-dev librocksdb
}
function linux_rocksdb_installer()
@ -669,7 +669,7 @@ function run_installer()
function build_parity()
{
info "Downloading Parity..."
git clone git@github.com:ethcore/parity
git clone https://github.com/ethcore/parity
cd parity
git submodule init
git submodule update
@ -688,7 +688,7 @@ function run_installer()
info "- Run tests with:"
info " ${b}cargo test --release --features ethcore/json-tests -p ethcore${reset}"
info "- Install the client with:"
info " ${b}sudo cp parity/target/release/parity${reset}"
info " ${b}sudo cp parity/target/release/parity${reset} /usr/local/bin"
echo
}

View File

@ -55,16 +55,19 @@ Parity. Ethereum Client.
Copyright 2015, 2016 Ethcore (UK) Limited
Usage:
parity [options] [ <enode>... ]
parity [options] [ --no-bootstrap | <enode>... ]
Options:
--chain CHAIN Specify the blockchain type. CHAIN may be either a JSON chain specification file
or frontier, mainnet, morden, or testnet [default: frontier].
-d --db-path PATH Specify the database & configuration directory path [default: $HOME/.parity]
--no-bootstrap Don't bother trying to connect to any nodes initially.
--listen-address URL Specify the IP/port on which to listen for peers [default: 0.0.0.0:30304].
--public-address URL Specify the IP/port on which peers may connect [default: 0.0.0.0:30304].
--address URL Equivalent to --listen-address URL --public-address URL.
--upnp Use UPnP to try to figure out the correct network settings.
--node-key KEY Specify node secret key as hex string.
--cache-pref-size BYTES Specify the prefered size of the blockchain cache in bytes [default: 16384].
--cache-max-size BYTES Specify the maximum size of the blockchain cache in bytes [default: 262144].
@ -75,7 +78,7 @@ Options:
-l --logging LOGGING Specify the logging level.
-v --version Show information about version.
-h --help Show this screen.
", flag_cache_pref_size: usize, flag_cache_max_size: usize, flag_address: Option<String>);
", flag_cache_pref_size: usize, flag_cache_max_size: usize, flag_address: Option<String>, flag_node_key: Option<String>);
fn setup_log(init: &str) {
let mut builder = LogBuilder::new();
@ -129,7 +132,11 @@ impl Configuration {
}
}
fn get_spec(&self) -> Spec {
fn path(&self) -> String {
self.args.flag_db_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap())
}
fn spec(&self) -> Spec {
match self.args.flag_chain.as_ref() {
"frontier" | "mainnet" => ethereum::new_frontier(),
"morden" | "testnet" => ethereum::new_morden(),
@ -138,14 +145,16 @@ impl Configuration {
}
}
fn get_init_nodes(&self, spec: &Spec) -> Vec<String> {
match self.args.arg_enode.len() {
0 => spec.nodes().clone(),
_ => self.args.arg_enode.clone(),
fn init_nodes(&self, spec: &Spec) -> Vec<String> {
if self.args.flag_no_bootstrap { Vec::new() } else {
match self.args.arg_enode.len() {
0 => spec.nodes().clone(),
_ => self.args.arg_enode.clone(),
}
}
}
fn get_net_addresses(&self) -> (SocketAddr, SocketAddr) {
fn net_addresses(&self) -> (SocketAddr, SocketAddr) {
let listen_address;
let public_address;
@ -183,7 +192,7 @@ fn main() {
return;
}
let spec = conf.get_spec();
let spec = conf.spec();
// Setup logging
setup_log(&conf.args.flag_logging);
@ -193,13 +202,14 @@ fn main() {
// Configure network
let mut net_settings = NetworkConfiguration::new();
net_settings.nat_enabled = conf.args.flag_upnp;
net_settings.boot_nodes = conf.get_init_nodes(&spec);
let (listen, public) = conf.get_net_addresses();
net_settings.boot_nodes = conf.init_nodes(&spec);
let (listen, public) = conf.net_addresses();
net_settings.listen_address = listen;
net_settings.public_address = public;
net_settings.use_secret = conf.args.flag_node_key.as_ref().map(|s| Secret::from_str(&s).expect("Invalid key string"));
// Build client
let mut service = ClientService::start(spec, net_settings).unwrap();
let mut service = ClientService::start(spec, net_settings, &Path::new(&conf.path())).unwrap();
let client = service.client().clone();
client.configure_cache(conf.args.flag_cache_pref_size, conf.args.flag_cache_max_size);
@ -251,7 +261,7 @@ impl Informant {
let sync_info = sync.status();
if let (_, &Some(ref last_cache_info), &Some(ref last_report)) = (self.chain_info.read().unwrap().deref(), self.cache_info.read().unwrap().deref(), self.report.read().unwrap().deref()) {
println!("[ {} {} ]---[ {} blk/s | {} tx/s | {} gas/s //··· {}/{} peers, {} downloaded, {}+{} queued ···// {} ({}) bl {} ({}) ex ]",
println!("[ #{} {} ]---[ {} blk/s | {} tx/s | {} gas/s //··· {}/{} peers, #{}, {}+{} queued ···// {} ({}) bl {} ({}) ex ]",
chain_info.best_block_number,
chain_info.best_block_hash,
(report.blocks_imported - last_report.blocks_imported) / dur,
@ -260,7 +270,7 @@ impl Informant {
sync_info.num_active_peers,
sync_info.num_peers,
sync_info.blocks_received,
sync_info.last_imported_block_number.unwrap_or(chain_info.best_block_number),
queue_info.unverified_queue_size,
queue_info.verified_queue_size,

View File

@ -9,13 +9,13 @@ authors = ["Ethcore <admin@ethcore.io"]
[dependencies]
serde = "0.6.7"
serde_macros = "0.6.10"
serde_macros = { git = "https://github.com/debris/serde", path = "serde_macros" }
serde_json = "0.6.0"
jsonrpc-core = "1.1"
jsonrpc-http-server = "1.1"
jsonrpc-core = { git = "https://github.com/debris/jsonrpc-core" }
jsonrpc-http-server = { git = "https://github.com/debris/jsonrpc-http-server" }
ethcore-util = { path = "../util" }
ethcore = { path = "../ethcore" }
ethsync = { path = "../sync" }
clippy = "0.0.37"
clippy = "0.0.41"
target_info = "0.1.0"
rustc-serialize = "0.3"

View File

@ -23,7 +23,6 @@ use util::uint::*;
use util::sha3::*;
use ethcore::client::*;
use ethcore::views::*;
use ethcore::blockchain::{BlockId, TransactionId};
use ethcore::ethereum::denominations::shannon;
use v1::traits::{Eth, EthFilter};
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index};
@ -42,6 +41,50 @@ impl EthClient {
sync: sync
}
}
fn block(&self, id: BlockId, include_txs: bool) -> Result<Value, Error> {
match (self.client.block(id.clone()), self.client.block_total_difficulty(id)) {
(Some(bytes), Some(total_difficulty)) => {
let block_view = BlockView::new(&bytes);
let view = block_view.header_view();
let block = Block {
hash: OptionalValue::Value(view.sha3()),
parent_hash: view.parent_hash(),
uncles_hash: view.uncles_hash(),
author: view.author(),
miner: view.author(),
state_root: view.state_root(),
transactions_root: view.transactions_root(),
receipts_root: view.receipts_root(),
number: OptionalValue::Value(U256::from(view.number())),
gas_used: view.gas_used(),
gas_limit: view.gas_limit(),
logs_bloom: view.log_bloom(),
timestamp: U256::from(view.timestamp()),
difficulty: view.difficulty(),
total_difficulty: total_difficulty,
uncles: vec![],
transactions: {
if include_txs {
BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect())
} else {
BlockTransactions::Hashes(block_view.transaction_hashes())
}
},
extra_data: Bytes::default()
};
to_value(&block)
},
_ => Ok(Value::Null)
}
}
fn transaction(&self, id: TransactionId) -> Result<Value, Error> {
match self.client.transaction(id) {
Some(t) => to_value(&Transaction::from(t)),
None => Ok(Value::Null)
}
}
}
impl Eth for EthClient {
@ -110,7 +153,7 @@ impl Eth for EthClient {
fn block_transaction_count(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params)
.and_then(|(hash,)| match self.client.block(&hash) {
.and_then(|(hash,)| match self.client.block(BlockId::Hash(hash)) {
Some(bytes) => to_value(&BlockView::new(&bytes).transactions_count()),
None => Ok(Value::Null)
})
@ -118,7 +161,7 @@ impl Eth for EthClient {
fn block_uncles_count(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params)
.and_then(|(hash,)| match self.client.block(&hash) {
.and_then(|(hash,)| match self.client.block(BlockId::Hash(hash)) {
Some(bytes) => to_value(&BlockView::new(&bytes).uncles_count()),
None => Ok(Value::Null)
})
@ -130,62 +173,29 @@ impl Eth for EthClient {
.and_then(|(address, _block_number)| to_value(&self.client.code(&address).map_or_else(Bytes::default, Bytes::new)))
}
fn block(&self, params: Params) -> Result<Value, Error> {
fn block_by_hash(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256, bool)>(params)
.and_then(|(hash, include_txs)| match (self.client.block(&hash), self.client.block_total_difficulty(&hash)) {
(Some(bytes), Some(total_difficulty)) => {
let block_view = BlockView::new(&bytes);
let view = block_view.header_view();
let block = Block {
hash: OptionalValue::Value(view.sha3()),
parent_hash: view.parent_hash(),
uncles_hash: view.uncles_hash(),
author: view.author(),
miner: view.author(),
state_root: view.state_root(),
transactions_root: view.transactions_root(),
receipts_root: view.receipts_root(),
number: OptionalValue::Value(U256::from(view.number())),
gas_used: view.gas_used(),
gas_limit: view.gas_limit(),
logs_bloom: view.log_bloom(),
timestamp: U256::from(view.timestamp()),
difficulty: view.difficulty(),
total_difficulty: total_difficulty,
uncles: vec![],
transactions: {
if include_txs {
BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect())
} else {
BlockTransactions::Hashes(block_view.transaction_hashes())
}
},
extra_data: Bytes::default()
};
to_value(&block)
},
_ => Ok(Value::Null)
})
.and_then(|(hash, include_txs)| self.block(BlockId::Hash(hash), include_txs))
}
fn block_by_number(&self, params: Params) -> Result<Value, Error> {
from_params::<(BlockNumber, bool)>(params)
.and_then(|(number, include_txs)| self.block(number.into(), include_txs))
}
fn transaction_by_hash(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params)
.and_then(|(hash,)| match self.client.transaction(TransactionId::Hash(hash)) {
Some(t) => to_value(&Transaction::from(t)),
None => Ok(Value::Null)
})
.and_then(|(hash,)| self.transaction(TransactionId::Hash(hash)))
}
fn transaction_by_block_hash_and_index(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256, Index)>(params)
.and_then(|(hash, index)| match self.client.transaction(TransactionId::Location(BlockId::Hash(hash), index.value())) {
Some(t) => to_value(&Transaction::from(t)),
None => Ok(Value::Null)
})
.and_then(|(hash, index)| self.transaction(TransactionId::Location(BlockId::Hash(hash), index.value())))
}
fn transaction_by_block_number_and_index(&self, _params: Params) -> Result<Value, Error> {
unimplemented!()
fn transaction_by_block_number_and_index(&self, params: Params) -> Result<Value, Error> {
from_params::<(BlockNumber, Index)>(params)
.and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value())))
}
}

View File

@ -50,8 +50,11 @@ pub trait Eth: Sized + Send + Sync + 'static {
/// Returns content of the storage at given address.
fn storage_at(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
/// Returns block with given index / hash.
fn block(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
/// Returns block with given hash.
fn block_by_hash(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
/// Returns block with given number.
fn block_by_number(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
/// Returns the number of transactions sent from given address at given time (block number).
fn transaction_count(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
@ -135,8 +138,8 @@ pub trait Eth: Sized + Send + Sync + 'static {
delegate.add_method("eth_sendTransaction", Eth::send_transaction);
delegate.add_method("eth_call", Eth::call);
delegate.add_method("eth_estimateGas", Eth::estimate_gas);
delegate.add_method("eth_getBlockByHash", Eth::block);
delegate.add_method("eth_getBlockByNumber", Eth::block);
delegate.add_method("eth_getBlockByHash", Eth::block_by_hash);
delegate.add_method("eth_getBlockByNumber", Eth::block_by_number);
delegate.add_method("eth_getTransactionByHash", Eth::transaction_by_hash);
delegate.add_method("eth_getTransactionByBlockHashAndIndex", Eth::transaction_by_block_hash_and_index);
delegate.add_method("eth_getTransactionByBlockNumberAndIndex", Eth::transaction_by_block_number_and_index);

View File

@ -16,6 +16,7 @@
use serde::{Deserialize, Deserializer, Error};
use serde::de::Visitor;
use ethcore::client::BlockId;
/// Represents rpc api block number param.
#[derive(Debug, PartialEq)]
@ -53,8 +54,20 @@ impl Visitor for BlockNumberVisitor {
}
}
impl Into<BlockId> for BlockNumber {
fn into(self) -> BlockId {
match self {
BlockNumber::Num(n) => BlockId::Number(n),
BlockNumber::Earliest => BlockId::Earliest,
BlockNumber::Latest => BlockId::Latest,
BlockNumber::Pending => BlockId::Latest // TODO: change this once blockid support pending
}
}
}
#[cfg(test)]
mod tests {
use ethcore::client::BlockId;
use super::*;
use serde_json;
@ -64,5 +77,13 @@ mod tests {
let deserialized: Vec<BlockNumber> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, vec![BlockNumber::Num(10), BlockNumber::Num(10), BlockNumber::Latest, BlockNumber::Earliest, BlockNumber::Pending])
}
#[test]
fn block_number_into() {
assert_eq!(BlockId::Number(100), BlockNumber::Num(100).into());
assert_eq!(BlockId::Earliest, BlockNumber::Earliest.into());
assert_eq!(BlockId::Latest, BlockNumber::Latest.into());
assert_eq!(BlockId::Latest, BlockNumber::Pending.into());
}
}

View File

@ -10,7 +10,7 @@ authors = ["Ethcore <admin@ethcore.io"]
[dependencies]
ethcore-util = { path = "../util" }
ethcore = { path = ".." }
clippy = "0.0.37"
clippy = "0.0.41"
log = "0.3"
env_logger = "0.3"
time = "0.1.34"

View File

@ -33,7 +33,7 @@ use util::*;
use std::mem::{replace};
use ethcore::views::{HeaderView};
use ethcore::header::{BlockNumber, Header as BlockHeader};
use ethcore::client::{BlockChainClient, BlockStatus};
use ethcore::client::{BlockChainClient, BlockStatus, BlockId};
use range_collection::{RangeCollection, ToUsize, FromUsize};
use ethcore::error::*;
use ethcore::block::Block;
@ -331,7 +331,7 @@ impl ChainSync {
self.highest_block = Some(number);
}
let hash = info.hash();
match io.chain().block_status(&hash) {
match io.chain().block_status(BlockId::Hash(hash.clone())) {
BlockStatus::InChain => {
self.have_common_block = true;
self.last_imported_block = Some(number);
@ -491,7 +491,7 @@ impl ChainSync {
for (rh, rd) in hashes {
let h = try!(rh);
let d = try!(rd);
match io.chain().block_status(&h) {
match io.chain().block_status(BlockId::Hash(h.clone())) {
BlockStatus::InChain => {
trace!(target: "sync", "New block hash already in chain {:?}", h);
},
@ -583,7 +583,7 @@ impl ChainSync {
trace!(target: "sync", "Starting sync with better chain");
self.request_headers_by_hash(io, peer_id, &peer_latest, 1, 0, false);
}
else if self.state == SyncState::Blocks {
else if self.state == SyncState::Blocks && io.chain().block_status(BlockId::Hash(peer_latest)) == BlockStatus::Unknown {
self.request_blocks(io, peer_id);
}
}
@ -607,7 +607,7 @@ impl ChainSync {
if self.have_common_block && !self.headers.is_empty() && self.headers.range_iter().next().unwrap().0 == self.current_base_block() + 1 {
for (start, ref items) in self.headers.range_iter() {
if needed_bodies.len() > MAX_BODIES_TO_REQUEST {
if needed_bodies.len() >= MAX_BODIES_TO_REQUEST {
break;
}
let mut index: BlockNumber = 0;
@ -654,7 +654,7 @@ impl ChainSync {
continue;
}
let mut block = prev;
while block < next && headers.len() <= MAX_HEADERS_TO_REQUEST {
while block < next && headers.len() < MAX_HEADERS_TO_REQUEST {
if !self.downloading_headers.contains(&(block as BlockNumber)) {
headers.push(block as BlockNumber);
self.downloading_headers.insert(block as BlockNumber);
@ -877,7 +877,7 @@ impl ChainSync {
// id is a hash
let hash: H256 = try!(r.val_at(0));
trace!(target: "sync", "-> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", hash, max_headers, skip, reverse);
match io.chain().block_header(&hash) {
match io.chain().block_header(BlockId::Hash(hash)) {
Some(hdr) => From::from(HeaderView::new(&hdr).number()),
None => last
}
@ -897,7 +897,7 @@ impl ChainSync {
let mut data = Bytes::new();
let inc = (skip + 1) as BlockNumber;
while number <= last && number > 0 && count < max_count {
if let Some(mut hdr) = io.chain().block_header_at(number) {
if let Some(mut hdr) = io.chain().block_header(BlockId::Number(number)) {
data.append(&mut hdr);
count += 1;
}
@ -929,7 +929,7 @@ impl ChainSync {
let mut added = 0usize;
let mut data = Bytes::new();
for i in 0..count {
if let Some(mut hdr) = io.chain().block_body(&try!(r.val_at::<H256>(i))) {
if let Some(mut hdr) = io.chain().block_body(BlockId::Hash(try!(r.val_at::<H256>(i)))) {
data.append(&mut hdr);
added += 1;
}
@ -1045,7 +1045,7 @@ impl ChainSync {
fn check_resume(&mut self, io: &mut SyncIo) {
if !io.chain().queue_info().is_full() && self.state == SyncState::Waiting {
self.state = SyncState::Idle;
self.state = SyncState::Blocks;
self.continue_sync(io);
}
}
@ -1060,7 +1060,8 @@ impl ChainSync {
let mut rlp_stream = RlpStream::new_list(route.blocks.len());
for block_hash in route.blocks {
let mut hash_rlp = RlpStream::new_list(2);
let difficulty = chain.block_total_difficulty(&block_hash).expect("Mallformed block without a difficulty on the chain!");
let difficulty = chain.block_total_difficulty(BlockId::Hash(block_hash.clone())).expect("Mallformed block without a difficulty on the chain!");
hash_rlp.append(&block_hash);
hash_rlp.append(&difficulty);
rlp_stream.append_raw(&hash_rlp.out(), 1);
@ -1076,7 +1077,7 @@ impl ChainSync {
/// creates latest block rlp for the given client
fn create_latest_block_rlp(chain: &BlockChainClient) -> Bytes {
let mut rlp_stream = RlpStream::new_list(2);
rlp_stream.append_raw(&chain.block(&chain.chain_info().best_block_hash).expect("Creating latest block when there is none"), 1);
rlp_stream.append_raw(&chain.block(BlockId::Hash(chain.chain_info().best_block_hash)).expect("Creating latest block when there is none"), 1);
rlp_stream.append(&chain.chain_info().total_difficulty);
rlp_stream.out()
}
@ -1088,10 +1089,10 @@ impl ChainSync {
let latest_hash = chain_info.best_block_hash;
let latest_number = chain_info.best_block_number;
self.peers.iter().filter(|&(_, peer_info)|
match io.chain().block_status(&peer_info.latest)
match io.chain().block_status(BlockId::Hash(peer_info.latest.clone()))
{
BlockStatus::InChain => {
let peer_number = HeaderView::new(&io.chain().block_header(&peer_info.latest).unwrap()).number();
let peer_number = HeaderView::new(&io.chain().block_header(BlockId::Hash(peer_info.latest.clone())).unwrap()).number();
peer_info.latest != latest_hash && latest_number > peer_number && latest_number - peer_number < MAX_PEER_LAG_PROPAGATION
},
_ => false
@ -1478,4 +1479,4 @@ mod tests {
let result = sync.on_peer_new_block(&mut io, 0, &UntrustedRlp::new(&data));
assert!(result.is_ok());
}
}
}

View File

@ -40,7 +40,7 @@ pub trait RangeCollection<K, V> {
fn get_tail(&mut self, key: &K) -> Range<K>;
/// Remove all elements < `start` in the range that contains `start` - 1
fn remove_head(&mut self, start: &K);
/// Remove all elements >= `start` in the range that contains `start`
/// Remove all elements >= `start` in the range that contains `start`
fn remove_tail(&mut self, start: &K);
/// Remove all elements >= `tail`
fn insert_item(&mut self, key: K, value: V);
@ -168,6 +168,7 @@ impl<K, V> RangeCollection<K, V> for Vec<(K, Vec<V>)> where K: Ord + PartialEq +
fn insert_item(&mut self, key: K, value: V) {
assert!(!self.have_item(&key));
// todo: fix warning
let lower = match self.binary_search_by(|&(k, _)| k.cmp(&key).reverse()) {
Ok(index) => index,
Err(index) => index,

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::*;
use ethcore::client::{BlockChainClient};
use ethcore::client::{BlockChainClient, BlockId};
use io::SyncIo;
use chain::{SyncState};
use super::helpers::*;
@ -27,7 +27,7 @@ fn two_peers() {
net.peer_mut(1).chain.add_blocks(1000, false);
net.peer_mut(2).chain.add_blocks(1000, false);
net.sync();
assert!(net.peer(0).chain.block_at(1000).is_some());
assert!(net.peer(0).chain.block(BlockId::Number(1000)).is_some());
assert_eq!(net.peer(0).chain.blocks.read().unwrap().deref(), net.peer(1).chain.blocks.read().unwrap().deref());
}
@ -60,7 +60,7 @@ fn empty_blocks() {
net.peer_mut(2).chain.add_blocks(5, n % 2 == 0);
}
net.sync();
assert!(net.peer(0).chain.block_at(1000).is_some());
assert!(net.peer(0).chain.block(BlockId::Number(1000)).is_some());
assert_eq!(net.peer(0).chain.blocks.read().unwrap().deref(), net.peer(1).chain.blocks.read().unwrap().deref());
}
@ -148,4 +148,4 @@ fn propagade_blocks() {
assert!(!net.peer(0).queue.is_empty());
// NEW_BLOCK_PACKET
assert_eq!(0x07, net.peer(0).queue[0].packet_id);
}
}

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::*;
use ethcore::client::{BlockChainClient, BlockStatus, TreeRoute, BlockChainInfo};
use ethcore::client::{BlockChainClient, BlockStatus, TreeRoute, BlockChainInfo, TransactionId, BlockId};
use ethcore::block_queue::BlockQueueInfo;
use ethcore::header::{Header as BlockHeader, BlockNumber};
use ethcore::error::*;
@ -23,7 +23,6 @@ use io::SyncIo;
use chain::{ChainSync};
use ethcore::receipt::Receipt;
use ethcore::transaction::LocalizedTransaction;
use ethcore::blockchain::TransactionId;
pub struct TestBlockChainClient {
pub blocks: RwLock<HashMap<H256, Bytes>>,
@ -77,10 +76,19 @@ impl TestBlockChainClient {
let index = blocks_read.len() - delta;
blocks_read[&index].clone()
}
fn block_hash(&self, id: BlockId) -> Option<H256> {
match id {
BlockId::Hash(hash) => Some(hash),
BlockId::Number(n) => self.numbers.read().unwrap().get(&(n as usize)).cloned(),
BlockId::Earliest => self.numbers.read().unwrap().get(&0).cloned(),
BlockId::Latest => self.numbers.read().unwrap().get(&(self.numbers.read().unwrap().len() - 1)).cloned()
}
}
}
impl BlockChainClient for TestBlockChainClient {
fn block_total_difficulty(&self, _h: &H256) -> Option<U256> {
fn block_total_difficulty(&self, _id: BlockId) -> Option<U256> {
Some(U256::zero())
}
@ -92,51 +100,28 @@ impl BlockChainClient for TestBlockChainClient {
unimplemented!();
}
fn block_header(&self, h: &H256) -> Option<Bytes> {
self.blocks.read().unwrap().get(h).map(|r| Rlp::new(r).at(0).as_raw().to_vec())
fn block_header(&self, id: BlockId) -> Option<Bytes> {
self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
}
fn block_body(&self, h: &H256) -> Option<Bytes> {
self.blocks.read().unwrap().get(h).map(|r| {
fn block_body(&self, id: BlockId) -> Option<Bytes> {
self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).map(|r| {
let mut stream = RlpStream::new_list(2);
stream.append_raw(Rlp::new(&r).at(1).as_raw(), 1);
stream.append_raw(Rlp::new(&r).at(2).as_raw(), 1);
stream.out()
})
}))
}
fn block(&self, h: &H256) -> Option<Bytes> {
self.blocks.read().unwrap().get(h).cloned()
fn block(&self, id: BlockId) -> Option<Bytes> {
self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).cloned())
}
fn block_status(&self, h: &H256) -> BlockStatus {
match self.blocks.read().unwrap().get(h) {
Some(_) => BlockStatus::InChain,
None => BlockStatus::Unknown
}
}
fn block_total_difficulty_at(&self, _number: BlockNumber) -> Option<U256> {
unimplemented!();
}
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes> {
self.numbers.read().unwrap().get(&(n as usize)).and_then(|h| self.block_header(h))
}
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes> {
self.numbers.read().unwrap().get(&(n as usize)).and_then(|h| self.block_body(h))
}
fn block_at(&self, n: BlockNumber) -> Option<Bytes> {
self.numbers.read().unwrap().get(&(n as usize)).map(|h| self.blocks.read().unwrap().get(h).unwrap().clone())
}
fn block_status_at(&self, n: BlockNumber) -> BlockStatus {
if (n as usize) < self.blocks.read().unwrap().len() {
BlockStatus::InChain
} else {
BlockStatus::Unknown
fn block_status(&self, id: BlockId) -> BlockStatus {
match id {
BlockId::Number(number) if (number as usize) < self.blocks.read().unwrap().len() => BlockStatus::InChain,
BlockId::Hash(ref hash) if self.blocks.read().unwrap().get(hash).is_some() => BlockStatus::InChain,
_ => BlockStatus::Unknown
}
}

View File

@ -26,7 +26,7 @@ crossbeam = "0.2"
slab = { git = "https://github.com/arkpar/slab.git" }
sha3 = { path = "sha3" }
serde = "0.6.7"
clippy = "0.0.37"
clippy = "0.0.41"
json-tests = { path = "json-tests" }
target_info = "0.1.0"
igd = "0.4.2"

View File

@ -17,7 +17,6 @@
#![feature(test)]
extern crate test;
extern crate rand;
extern crate ethcore_util;
#[macro_use]
extern crate log;

View File

@ -74,7 +74,6 @@ impl From<::secp256k1::Error> for CryptoError {
match e {
::secp256k1::Error::InvalidMessage => CryptoError::InvalidMessage,
::secp256k1::Error::InvalidPublicKey => CryptoError::InvalidPublic,
::secp256k1::Error::InvalidSignature => CryptoError::InvalidSignature,
::secp256k1::Error::InvalidSecretKey => CryptoError::InvalidSecret,
_ => CryptoError::InvalidSignature,
}

View File

@ -296,7 +296,7 @@ macro_rules! impl_hash {
try!(write!(f, "{:02x}", i));
}
try!(write!(f, ""));
for i in &self.0[$size - 4..$size] {
for i in &self.0[$size - 2..$size] {
try!(write!(f, "{:02x}", i));
}
Ok(())
@ -647,7 +647,7 @@ mod tests {
fn hash() {
let h = H64([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
assert_eq!(H64::from_str("0123456789abcdef").unwrap(), h);
assert_eq!(format!("{}", h), "0123…89abcdef");
assert_eq!(format!("{}", h), "0123…cdef");
assert_eq!(format!("{:?}", h), "0123456789abcdef");
assert_eq!(h.hex(), "0123456789abcdef");
assert!(h == h);

View File

@ -47,10 +47,10 @@ impl Clone for JournalDB {
}
}
const LAST_ERA_KEY : [u8; 4] = [ b'l', b'a', b's', b't' ];
const LATEST_ERA_KEY : [u8; 4] = [ b'l', b'a', b's', b't' ];
const VERSION_KEY : [u8; 4] = [ b'j', b'v', b'e', b'r' ];
const DB_VERSION: u32 = 1;
const DB_VERSION: u32 = 2;
impl JournalDB {
/// Create a new instance given a `backing` database.
@ -87,7 +87,7 @@ impl JournalDB {
/// Check if this database has any commits
pub fn is_empty(&self) -> bool {
self.backing.get(&LAST_ERA_KEY).expect("Low level database error").is_none()
self.backing.get(&LATEST_ERA_KEY).expect("Low level database error").is_none()
}
/// Commit all recent insert operations and historical removals from the old era
@ -144,6 +144,7 @@ impl JournalDB {
r.append(&inserts);
r.append(&removes);
try!(batch.put(&last, r.as_raw()));
try!(batch.put(&LATEST_ERA_KEY, &encode(&now)));
}
// apply old commits' details
@ -181,7 +182,6 @@ impl JournalDB {
try!(batch.delete(&h));
deletes += 1;
}
try!(batch.put(&LAST_ERA_KEY, &encode(&end_era)));
trace!("JournalDB: delete journal for time #{}.{}, (canon was {}): {} entries", end_era, index, canon_id, deletes);
}
@ -228,8 +228,8 @@ impl JournalDB {
fn read_counters(db: &DB) -> HashMap<H256, i32> {
let mut res = HashMap::new();
if let Some(val) = db.get(&LAST_ERA_KEY).expect("Low-level database error.") {
let mut era = decode::<u64>(&val) + 1;
if let Some(val) = db.get(&LATEST_ERA_KEY).expect("Low-level database error.") {
let mut era = decode::<u64>(&val);
loop {
let mut index = 0usize;
while let Some(rlp_data) = db.get({
@ -245,10 +245,10 @@ impl JournalDB {
}
index += 1;
};
if index == 0 {
if index == 0 || era == 0 {
break;
}
era += 1;
era -= 1;
}
}
trace!("Recovered {} counters", res.len());
@ -426,4 +426,32 @@ mod tests {
jdb.commit(2, &b"2a".sha3(), Some((1, b"1a".sha3()))).unwrap();
assert!(jdb.exists(&foo));
}
#[test]
fn reopen() {
use rocksdb::DB;
let mut dir = ::std::env::temp_dir();
dir.push(H32::random().hex());
let foo = {
let mut jdb = JournalDB::new(DB::open_default(dir.to_str().unwrap()).unwrap());
// history is 1
let foo = jdb.insert(b"foo");
jdb.commit(0, &b"0".sha3(), None).unwrap();
foo
};
{
let mut jdb = JournalDB::new(DB::open_default(dir.to_str().unwrap()).unwrap());
jdb.remove(&foo);
jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap();
}
{
let mut jdb = JournalDB::new(DB::open_default(dir.to_str().unwrap()).unwrap());
assert!(jdb.exists(&foo));
jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap();
assert!(!jdb.exists(&foo));
}
}
}

View File

@ -211,7 +211,7 @@ impl Discovery {
}
let mut ret:Vec<&NodeId> = Vec::new();
for (_, nodes) in found {
for nodes in found.values() {
for n in nodes {
if ret.len() < BUCKET_SIZE as usize /* && n->endpoint && n->endpoint.isAllowed() */ {
ret.push(n);

View File

@ -412,7 +412,7 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
let mut to_kill = Vec::new();
for e in self.connections.write().unwrap().iter_mut() {
if let ConnectionEntry::Session(ref mut s) = *e.lock().unwrap().deref_mut() {
if !s.keep_alive() {
if !s.keep_alive(io) {
s.disconnect(DisconnectReason::PingTimeout);
to_kill.push(s.token());
}

View File

@ -180,7 +180,7 @@ impl Session {
}
/// Keep this session alive. Returns false if ping timeout happened
pub fn keep_alive(&mut self) -> bool {
pub fn keep_alive<Message>(&mut self, io: &IoContext<Message>) -> bool where Message: Send + Sync + Clone {
let timed_out = if let Some(pong) = self.pong_time_ns {
pong - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000
} else {
@ -191,6 +191,7 @@ impl Session {
if let Err(e) = self.send_ping() {
debug!("Error sending ping message: {:?}", e);
}
io.update_registration(self.token()).unwrap_or_else(|e| debug!(target: "net", "Session registration error: {:?}", e));
}
!timed_out
}
@ -324,7 +325,7 @@ impl Session {
let mut rlp = RlpStream::new();
rlp.append(&(PACKET_DISCONNECT as u32));
rlp.begin_list(1);
rlp.append(&(reason.clone() as u32));
rlp.append(&(reason as u32));
self.connection.send_packet(&rlp.out()).ok();
NetworkError::Disconnect(reason)
}

View File

@ -408,7 +408,7 @@ impl Decodable for Vec<u8> {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
decoder.read_value(| bytes | {
let mut res = vec![];
res.extend(bytes);
res.extend_from_slice(bytes);
Ok(res)
})
}

View File

@ -293,7 +293,7 @@ impl<'a> Iterator for TrieDBIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
let b = match self.trail.last_mut() {
Some(ref mut b) => { b.increment(); b.clone() },
Some(mut b) => { b.increment(); b.clone() },
None => return None
};
match (b.status, b.node) {
@ -309,9 +309,8 @@ impl<'a> Iterator for TrieDBIterator<'a> {
self.trail.pop();
self.next()
},
(Status::At, Node::Leaf(_, v)) => Some((self.key(), v)),
(Status::At, Node::Leaf(_, v)) | (Status::At, Node::Branch(_, Some(v))) => Some((self.key(), v)),
(Status::At, Node::Extension(_, d)) => self.descend_next(d),
(Status::At, Node::Branch(_, Some(v))) => Some((self.key(), v)),
(Status::At, Node::Branch(_, _)) => self.next(),
(Status::AtChild(i), Node::Branch(children, _)) if children[i].len() > 0 => {
match i {