Merge branch 'master' into nvolf

This commit is contained in:
Nikolay Volf 2016-02-03 19:00:05 +03:00
commit f85b9eb75b
90 changed files with 2328 additions and 907 deletions

View File

@ -4,11 +4,13 @@ language: rust
branches:
only:
- master
- /^beta-.*$/
- /^stable-.*$/
matrix:
fast_finish: true
include:
- rust: nightly
env: FEATURES="--features ethcore/json-tests" KCOV_FEATURES="" TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity"
env: FEATURES="--features ethcore/json-tests" KCOV_FEATURES="" TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity" ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}"
cache:
apt: true
directories:
@ -30,6 +32,7 @@ script:
- cargo build --release --verbose ${FEATURES}
- cargo test --release --verbose ${FEATURES} ${TARGETS}
- cargo bench --no-run ${FEATURES} ${TARGETS}
- tar cvzf parity${ARCHIVE_SUFFIX}.tar.gz -C target/release parity
after_success: |
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. &&
@ -46,10 +49,18 @@ after_success: |
cargo doc --no-deps --verbose ${KCOV_FEATURES} ${TARGETS} &&
echo '<meta http-equiv=refresh content=0;url=ethcore/index.html>' > target/doc/index.html &&
pip install --user ghp-import &&
/home/travis/.local/bin/ghp-import -n target/doc
#&&
#git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
/home/travis/.local/bin/ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
- secure: 3sUjNi9mhdL5h1GTm8LONnDN/SYvUHT+WSkMl93h3nYiLCQXk8eZaPS98AS7oOaTsfW4UvnwckVFCFl49ttInsv4cd/TkAxmrJHe6kPyS9/4NWUdmP8BjicbBvL/ioSdXMECMEYzPDLV+I3KhtC2LcB6ceDEl/XwMOJlzbGf7RbtcXGVQgMLqSYY1YKjQA4vbT5nFgIS/sZu3Z9yFgN0GafnihKcizqoHhdJjs/zxmX+qJepnC6o3V6KcFnS7QHhM1JOr85twE6S422UlvNaEb5ovwLPqmOl5+fA+6shbx4AxFTY6E9Iors+OVY/JliFhrqOdCt0i2P1FUHN4kbGZQkf0rphN/ZOI2uKNFTOyXiPvppfo/ZemKmcqkwkqP9+lf5QqYmtE6hsAYagxn49xJZILl8tAYbdqxF5gxa+TEVrfsBFtz/Sv3q8QhKQNPAmjEcKyMatyEreLUIFEpFTGIco8jN4eXeSoLRdJ+Z75ihttfQWhNfUDgNL30iQLy0AgFSsh/cyb5M8y9lxrGDzDTogvaiKGwr/V45sPkcXWCkmOgMdINqBB6ZtdL3bGHdyjmYj+y3btjf3aP11k++BL0fXIaKn25aS/p/9iyGb1FyGCM03o4ZRQ3YhTOvfMRfRGf6nWbaMx9upv8o5ShSdysewhrnh3082r7u896ny1Ho=
- secure: 0/FeVvFl3AhBW0TCPoujY9zOAYoUNMlAz3XjC04vlc4Ksfx0lGU3KFi97LlALxMWV0lfwQc7ixSe2vTgQVQuLVSU9XEW40fQgEjJlmLca2RcRx1kfzJDypuWSiCME7MWmLPH0ac4COdTDS1z5WGggv5YB7GQPCzFvcmOOaPYtF29ngCtkyB2HmNkY/W3omHFEk7Si6bsmOSHZiOAhivPl6ixnGpFyTEKPyraMMqPIj5rbEGkzgeLTiXf2ur143n/tnSr8tmP1MfQi9yS8/ONidMqnxUeuLkeNnb82zj9pVJhVXq0xF44WXJ8Za1jm0ByiTakgqpm8Juk822qjvtNulJ1XZW/fyZQZaN1dy3uq5Ud3W8wS9M7VIVl8CoXozzDpIsdPeUAtkAxeHBsZqL1vAH2yC1YJA7HPySMYzCjYqkJ2r62xYk0gXmNXphfU+F/X/rHzHsTMJPONJ54HQwu12m7zVlKIYBGHgEXg/HAM/g4ljUzl6WWR/nHH/tQM8ND/8FpHluJSZJWacq/1QNhVdTq2x6cqws2fs5A7nVpccR9+6RRgYgv6+YS2LxvFzByuZveGGoKif+uMECXN876j40araUqU528Yz9i8bHJlnM3coRBndaLNWByLcUyXCB9r9IUosUu41rr+L2mVzkSDm0GicuNCzqvzYQ9Q6QY4uQ=
deploy:
provider: releases
api_key:
secure: "t+oGT/4lsy7IScw5s86Dpntl5Nyck4qG6nhHwMScc6FYzwLldgwgJaafL8Ej+HG+b7nFLriN+Snoa4YQ5o74X5ZlSWubVREOYQlL/fq7vcPB0DwAZ0Jufq1QW2R1M+3SwwF1eAwTv2W3G7A2K7dxjCVvENcy/gdxnZ36NeUPsqaCC9UcI2Yc7+4jyQwvx6ZfBvQeu+HbKENA0eUNs2ZQOID/1IPy0LJBvSyxAQYsysXdjTzGdNu4+Iba20E8uWYe4fAbgz+gwGarXg1L6D6gKyMlWkViqWjvXWBuDJJqMQZ3rw41AwZOoh3mKd2Lc0l6l4oZcEqPuob0yKTNjz1tuJy9xKTC2F2bDzsvUgk1IRfMK5ukXXXS09ZCZWuA9/GtnsqJ1xGTiwX+DhQzpVBHaBiseSNlYE1YN/3jNyGY+iSts1qut+1BwE7swmcTLsAPoAy8Ue+f7ErNoCg1lm71vq7VO2DLn7x2NqHyHUEuJ+7olDHSdE84G7d9otDRu/+TfMOw7GXwTaha6yJRInuNsnj4CFMLNVvYACzCC2idB7f7nUZoSFi9jf18S9fCMPVmazMrFj4g95HWrVHkjpV5zRTeUdTWw6DJl6pC9HFqORHdCvLv4Rc4dm5r3CmOcAQ0ZuiccV2oKzw4/Wic96daae8M5f5KSQ/WTr+h0wXZKp0="
skip_cleanup: true
file: parity${ARCHIVE_SUFFIX}.tar.gz
on:
tags: true

View File

@ -7,10 +7,9 @@
[coveralls-image]: https://coveralls.io/repos/github/ethcore/parity/badge.svg?branch=master&t=Fk0OuQ
[coveralls-url]: https://coveralls.io/r/ethcore/parity?branch=master
### Building from source
##### Ubuntu 14.04 and later
##### Ubuntu 14.04
```bash
# install rocksdb
@ -22,10 +21,8 @@ apt-get install -y --force-yes librocksdb
curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes
# install nightly and make it default
multirust update nightly && multirust default nightly
# export rust LIBRARY_PATH
export LIBRARY_PATH=/usr/local/lib
multirust update nightly
multirust default nightly
# download and build parity
git clone https://github.com/ethcore/parity
@ -33,7 +30,31 @@ cd parity
cargo build --release
```
##### OSX
##### Linux
```bash
# install rocksdb
git clone --tag v4.1 --depth=1 https://github.com/facebook/rocksdb.git
cd rocksdb
make shared_lib
sudo cp -a librocksdb.so* /usr/lib
sudo ldconfig
cd ..
# install rust nightly
curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes
# install nightly and make it default
sudo multirust update nightly
sudo multirust default nightly
# download and build parity
git clone https://github.com/ethcore/parity
cd parity
cargo build --release
```
##### OSX with Homebrew
```bash
# install rocksdb && multirust
@ -44,9 +65,6 @@ brew install multirust
# install nightly and make it default
multirust update nightly && multirust default nightly
# export rust LIBRARY_PATH
export LIBRARY_PATH=/usr/local/lib
# download and build parity
git clone https://github.com/ethcore/parity
cd parity

4
doc.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
# generate documentation only for partiy and ethcore libraries
cargo doc --no-deps --verbose -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity

View File

@ -10,12 +10,10 @@ authors = ["Ethcore <admin@ethcore.io>"]
log = "0.3"
env_logger = "0.3"
rustc-serialize = "0.3"
flate2 = "0.2"
rocksdb = "0.3"
heapsize = "0.2.0"
rust-crypto = "0.2.34"
time = "0.1"
#interpolate_idents = { git = "https://github.com/SkylerLipthay/interpolate_idents" }
ethcore-util = { path = "../util" }
evmjit = { path = "../evmjit", optional = true }
ethash = { path = "../ethash" }

View File

@ -1,3 +1,5 @@
//! Single account in the system.
use util::*;
use pod_account::*;
@ -19,6 +21,7 @@ pub struct Account {
}
impl Account {
#[cfg(test)]
/// General constructor.
pub fn new(balance: U256, nonce: U256, storage: HashMap<H256, H256>, code: Bytes) -> Account {
Account {
@ -31,6 +34,8 @@ impl Account {
}
}
#[cfg(test)]
#[cfg(feature = "json-tests")]
/// General constructor.
pub fn from_pod(pod: PodAccount) -> Account {
Account {
@ -81,15 +86,8 @@ impl Account {
}
}
/// Reset this account to the status of a not-yet-initialised contract.
/// NOTE: Account should have `init_code()` called on it later.
pub fn reset_code(&mut self) {
self.code_hash = None;
self.code_cache = vec![];
}
/// Set this account's code to the given code.
/// NOTE: Account should have been created with `new_contract()` or have `reset_code()` called on it.
/// NOTE: Account should have been created with `new_contract()`
pub fn init_code(&mut self, code: Bytes) {
assert!(self.code_hash.is_none());
self.code_cache = code;
@ -113,6 +111,7 @@ impl Account {
/// return the nonce associated with this account.
pub fn nonce(&self) -> &U256 { &self.nonce }
#[cfg(test)]
/// return the code hash associated with this account.
pub fn code_hash(&self) -> H256 {
self.code_hash.clone().unwrap_or(SHA3_EMPTY)
@ -129,6 +128,7 @@ impl Account {
}
}
#[cfg(test)]
/// Provide a byte array which hashes to the `code_hash`. returns the hash as a result.
pub fn note_code(&mut self, code: Bytes) -> Result<(), H256> {
let h = code.sha3();
@ -163,18 +163,14 @@ impl Account {
}
}
/// return the storage root associated with this account.
pub fn base_root(&self) -> &H256 { &self.storage_root }
#[cfg(test)]
/// Determine whether there are any un-`commit()`-ed storage-setting operations.
pub fn storage_is_clean(&self) -> bool { self.storage_overlay.borrow().iter().find(|&(_, &(f, _))| f == Filth::Dirty).is_none() }
#[cfg(test)]
/// return the storage root associated with this account or None if it has been altered via the overlay.
pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} }
/// return the storage root associated with this account or None if it has been altered via the overlay.
pub fn recent_storage_root(&self) -> &H256 { &self.storage_root }
/// return the storage overlay.
pub fn storage_overlay(&self) -> Ref<HashMap<H256, (Filth, H256)>> { self.storage_overlay.borrow() }

View File

@ -1,15 +1,18 @@
//! Diff between two accounts.
use util::*;
#[cfg(test)]
use pod_account::*;
#[derive(Debug,Clone,PartialEq,Eq)]
/// Change in existance type.
// TODO: include other types of change.
pub enum Existance {
/// TODO [Gav Wood] Please document me
/// Item came into existance.
Born,
/// TODO [Gav Wood] Please document me
/// Item stayed in existance.
Alive,
/// TODO [Gav Wood] Please document me
/// Item went out of existance.
Died,
}
@ -25,20 +28,20 @@ impl fmt::Display for Existance {
}
#[derive(Debug,Clone,PartialEq,Eq)]
/// TODO [Gav Wood] Please document me
/// Account diff.
pub struct AccountDiff {
/// TODO [Gav Wood] Please document me
pub balance: Diff<U256>, // Allowed to be Same
/// TODO [Gav Wood] Please document me
/// Change in balance, allowed to be `Diff::Same`.
pub balance: Diff<U256>,
/// Change in nonce, allowed to be `Diff::Same`.
pub nonce: Diff<U256>, // Allowed to be Same
/// TODO [Gav Wood] Please document me
/// Change in code, allowed to be `Diff::Same`.
pub code: Diff<Bytes>, // Allowed to be Same
/// TODO [Gav Wood] Please document me
pub storage: BTreeMap<H256, Diff<H256>>,// Not allowed to be Same
/// Change in storage, values are not allowed to be `Diff::Same`.
pub storage: BTreeMap<H256, Diff<H256>>,
}
impl AccountDiff {
/// TODO [Gav Wood] Please document me
/// Get `Existance` projection.
pub fn existance(&self) -> Existance {
match self.balance {
Diff::Born(_) => Existance::Born,
@ -47,7 +50,9 @@ impl AccountDiff {
}
}
/// TODO [Gav Wood] Please document me
#[cfg(test)]
/// Determine difference between two optionally existant `Account`s. Returns None
/// if they are the same.
pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option<AccountDiff> {
match (pre, post) {
(None, Some(x)) => Some(AccountDiff {

View File

@ -1,3 +1,5 @@
//! Ethcore basic typenames.
use util::*;
/// Type for a 2048-bit log-bloom, as used by our blocks.
@ -6,10 +8,10 @@ pub type LogBloom = H2048;
/// Constant 2048-bit datum for 0. Often used as a default.
pub static ZERO_LOGBLOOM: LogBloom = H2048([0x00; 256]);
/// TODO [Gav Wood] Please document me
/// Semantic boolean for when a seal/signature is included.
pub enum Seal {
/// TODO [Gav Wood] Please document me
/// The seal/signature is included.
With,
/// TODO [Gav Wood] Please document me
/// The seal/signature is not included.
Without,
}

View File

@ -1,3 +1,5 @@
//! Blockchain block.
#![allow(ptr_arg)] // Because of &LastHashes -> &Vec<_>
use common::*;
@ -18,7 +20,7 @@ pub struct Block {
}
impl Block {
/// Returns true iff the given bytes form a valid encoding of a block in RLP.
/// Returns true if the given bytes form a valid encoding of a block in RLP.
// TODO: implement Decoder for this and have this use that.
pub fn is_good(b: &[u8]) -> bool {
/*
@ -71,16 +73,15 @@ pub struct ExecutedBlock {
/// A set of references to `ExecutedBlock` fields that are publicly accessible.
pub struct BlockRefMut<'a> {
/// TODO [Gav Wood] Please document me
/// Block header.
pub header: &'a Header,
/// TODO [Gav Wood] Please document me
/// Block transactions.
pub transactions: &'a Vec<Transaction>,
/// TODO [Gav Wood] Please document me
/// Block uncles.
pub uncles: &'a Vec<Header>,
/// TODO [Gav Wood] Please document me
/// Transaction receipts.
pub receipts: &'a Vec<Receipt>,
/// TODO [Gav Wood] Please document me
/// State.
pub state: &'a mut State,
}

View File

@ -9,6 +9,7 @@ use engine::Engine;
use views::*;
use header::*;
use service::*;
use client::BlockStatus;
/// Block queue status
#[derive(Debug)]
@ -41,7 +42,7 @@ pub struct BlockQueue {
deleting: Arc<AtomicBool>,
ready_signal: Arc<QueueSignal>,
empty: Arc<Condvar>,
processing: HashSet<H256>
processing: RwLock<HashSet<H256>>
}
struct UnVerifiedBlock {
@ -106,7 +107,7 @@ impl BlockQueue {
verification: verification.clone(),
verifiers: verifiers,
deleting: deleting.clone(),
processing: HashSet::new(),
processing: RwLock::new(HashSet::new()),
empty: empty.clone(),
}
}
@ -196,11 +197,22 @@ impl BlockQueue {
}
}
/// Check if the block is currently in the queue
pub fn block_status(&self, hash: &H256) -> BlockStatus {
if self.processing.read().unwrap().contains(&hash) {
return BlockStatus::Queued;
}
if self.verification.lock().unwrap().bad.contains(&hash) {
return BlockStatus::Bad;
}
BlockStatus::Unknown
}
/// Add a block to the queue.
pub fn import_block(&mut self, bytes: Bytes) -> ImportResult {
let header = BlockView::new(&bytes).header();
let h = header.hash();
if self.processing.contains(&h) {
if self.processing.read().unwrap().contains(&h) {
return Err(ImportError::AlreadyQueued);
}
{
@ -217,7 +229,7 @@ impl BlockQueue {
match verify_block_basic(&header, &bytes, self.engine.deref().deref()) {
Ok(()) => {
self.processing.insert(h.clone());
self.processing.write().unwrap().insert(h.clone());
self.verification.lock().unwrap().unverified.push_back(UnVerifiedBlock { header: header, bytes: bytes });
self.more_to_verify.notify_all();
Ok(h)
@ -235,10 +247,12 @@ impl BlockQueue {
let mut verification_lock = self.verification.lock().unwrap();
let mut verification = verification_lock.deref_mut();
verification.bad.insert(hash.clone());
self.processing.write().unwrap().remove(&hash);
let mut new_verified = VecDeque::new();
for block in verification.verified.drain(..) {
if verification.bad.contains(&block.header.parent_hash) {
verification.bad.insert(block.header.hash());
self.processing.write().unwrap().remove(&block.header.hash());
}
else {
new_verified.push_back(block);
@ -247,6 +261,15 @@ impl BlockQueue {
verification.verified = new_verified;
}
/// Mark given block as processed
pub fn mark_as_good(&mut self, hashes: &[H256]) {
let mut processing = self.processing.write().unwrap();
for h in hashes {
processing.remove(&h);
}
//TODO: reward peers
}
/// Removes up to `max` verified blocks from the queue
pub fn drain(&mut self, max: usize) -> Vec<PreVerifiedBlock> {
let mut verification = self.verification.lock().unwrap();
@ -254,7 +277,6 @@ impl BlockQueue {
let mut result = Vec::with_capacity(count);
for _ in 0..count {
let block = verification.verified.pop_front().unwrap();
self.processing.remove(&block.header.hash());
result.push(block);
}
self.ready_signal.reset();
@ -294,6 +316,7 @@ mod tests {
use block_queue::*;
use tests::helpers::*;
use error::*;
use views::*;
fn get_test_queue() -> BlockQueue {
let spec = get_test_spec();
@ -339,11 +362,14 @@ mod tests {
#[test]
fn returns_ok_for_drained_duplicates() {
let mut queue = get_test_queue();
if let Err(e) = queue.import_block(get_good_dummy_block()) {
let block = get_good_dummy_block();
let hash = BlockView::new(&block).header().hash().clone();
if let Err(e) = queue.import_block(block) {
panic!("error importing block that is valid by definition({:?})", e);
}
queue.flush();
queue.drain(10);
queue.mark_as_good(&[ hash ]);
if let Err(e) = queue.import_block(get_good_dummy_block()) {
panic!("error importing block that has already been drained ({:?})", e);

View File

@ -1,4 +1,4 @@
//! Fast access to blockchain data.
//! Blockchain database.
use util::*;
use rocksdb::{DB, WriteBatch, Writable};
@ -8,33 +8,27 @@ use transaction::*;
use views::*;
/// Represents a tree route between `from` block and `to` block:
///
/// - `blocks` - a vector of hashes of all blocks, ordered from `from` to `to`.
///
/// - `ancestor` - best common ancestor of these blocks.
///
/// - `index` - an index where best common ancestor would be.
pub struct TreeRoute {
/// TODO [debris] Please document me
/// A vector of hashes of all blocks, ordered from `from` to `to`.
pub blocks: Vec<H256>,
/// TODO [debris] Please document me
/// Best common ancestor of these blocks.
pub ancestor: H256,
/// TODO [debris] Please document me
/// An index where best common ancestor would be.
pub index: usize
}
/// Represents blockchain's in-memory cache size in bytes.
#[derive(Debug)]
pub struct CacheSize {
/// TODO [debris] Please document me
/// Blocks cache size.
pub blocks: usize,
/// TODO [debris] Please document me
/// BlockDetails cache size.
pub block_details: usize,
/// TODO [debris] Please document me
/// Transaction addresses cache size.
pub transaction_addresses: usize,
/// TODO [debris] Please document me
/// Logs cache size.
pub block_logs: usize,
/// TODO [debris] Please document me
/// Blooms cache size.
pub blocks_blooms: usize
}

View File

@ -63,7 +63,8 @@ impl Builtin {
}
}
/// TODO [Gav Wood] Please document me
/// Copy a bunch of bytes to a destination; if the `src` is too small to fill `dest`,
/// leave the rest unchanged.
pub fn copy_to(src: &[u8], dest: &mut[u8]) {
// NICE: optimise
for i in 0..min(src.len(), dest.len()) {

View File

@ -1,3 +1,5 @@
//! Blockchain database client.
use util::*;
use rocksdb::{Options, DB};
use blockchain::{BlockChain, BlockProvider, CacheSize};
@ -13,9 +15,10 @@ use service::NetSyncMessage;
use env_info::LastHashes;
use verification::*;
use block::*;
pub use blockchain::TreeRoute;
/// General block status
#[derive(Debug)]
#[derive(Debug, Eq, PartialEq)]
pub enum BlockStatus {
/// Part of the blockchain.
InChain,
@ -48,8 +51,6 @@ impl fmt::Display for BlockChainInfo {
}
}
/// TODO [arkpar] Please document me
pub type TreeRoute = ::blockchain::TreeRoute;
/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send {
@ -114,18 +115,18 @@ pub trait BlockChainClient : Sync + Send {
}
#[derive(Default, Clone, Debug, Eq, PartialEq)]
/// TODO [Gav Wood] Please document me
/// Report on the status of a client.
pub struct ClientReport {
/// TODO [Gav Wood] Please document me
/// How many blocks have been imported so far.
pub blocks_imported: usize,
/// TODO [Gav Wood] Please document me
/// How many transactions have been applied so far.
pub transactions_applied: usize,
/// TODO [Gav Wood] Please document me
/// How much gas has been processed so far.
pub gas_processed: U256,
}
impl ClientReport {
/// TODO [Gav Wood] Please document me
/// Alter internal reporting to reflect the additional `block` has been processed.
pub fn accrue_block(&mut self, block: &PreVerifiedBlock) {
self.blocks_imported += 1;
self.transactions_applied += block.transactions.len();
@ -204,6 +205,7 @@ impl Client {
let mut bad = HashSet::new();
let _import_lock = self.import_lock.lock();
let blocks = self.block_queue.write().unwrap().drain(128);
let mut good_blocks = Vec::with_capacity(128);
for block in blocks {
if bad.contains(&block.header.parent_hash) {
self.block_queue.write().unwrap().mark_as_bad(&block.header.hash());
@ -256,6 +258,8 @@ impl Client {
break;
}
good_blocks.push(header.hash().clone());
self.chain.write().unwrap().insert_block(&block.bytes); //TODO: err here?
let ancient = if header.number() >= HISTORY { Some(header.number() - HISTORY) } else { None };
match result.drain().commit(header.number(), &header.hash(), ancient.map(|n|(n, self.chain.read().unwrap().block_hash(n).unwrap()))) {
@ -269,6 +273,7 @@ impl Client {
trace!(target: "client", "Imported #{} ({})", header.number(), header.hash());
ret += 1;
}
self.block_queue.write().unwrap().mark_as_good(&good_blocks);
ret
}
@ -323,7 +328,11 @@ impl BlockChainClient for Client {
}
fn block_status(&self, hash: &H256) -> BlockStatus {
if self.chain.read().unwrap().is_known(&hash) { BlockStatus::InChain } else { BlockStatus::Unknown }
if self.chain.read().unwrap().is_known(&hash) {
BlockStatus::InChain
} else {
self.block_queue.read().unwrap().block_status(hash)
}
}
fn block_total_difficulty(&self, hash: &H256) -> Option<U256> {
@ -370,6 +379,9 @@ 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 {
return Err(ImportError::UnknownParent);
}
self.block_queue.write().unwrap().import_block(bytes)
}

View File

@ -31,17 +31,16 @@ pub trait Engine : Sync + Send {
/// Some intrinsic operation parameters; by default they take their value from the `spec()`'s `engine_params`.
fn maximum_extra_data_size(&self) -> usize { decode(&self.spec().engine_params.get("maximumExtraDataSize").unwrap()) }
/// TODO [Gav Wood] Please document me
/// Maximum number of uncles a block is allowed to declare.
fn maximum_uncle_count(&self) -> usize { 2 }
/// TODO [Gav Wood] Please document me
/// The nonce with which accounts begin.
fn account_start_nonce(&self) -> U256 { decode(&self.spec().engine_params.get("accountStartNonce").unwrap()) }
/// Block transformation functions, before and after the transactions.
/// Block transformation functions, before the transactions.
fn on_new_block(&self, _block: &mut ExecutedBlock) {}
/// TODO [Gav Wood] Please document me
/// Block transformation functions, after the transactions.
fn on_close_block(&self, _block: &mut ExecutedBlock) {}
// TODO: consider including State in the params for verification functions.
/// Phase 1 quick block verification. Only does checks that are cheap. `block` (the header's full block)
/// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import.
fn verify_block_basic(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) }
@ -58,7 +57,7 @@ pub trait Engine : Sync + Send {
// TODO: Add flags for which bits of the transaction to check.
// TODO: consider including State in the params.
fn verify_transaction_basic(&self, _t: &Transaction, _header: &Header) -> Result<(), Error> { Ok(()) }
/// TODO [Gav Wood] Please document me
/// Verify a particular transaction is valid.
fn verify_transaction(&self, _t: &Transaction, _header: &Header) -> Result<(), Error> { Ok(()) }
/// Don't forget to call Super::populateFromParent when subclassing & overriding.
@ -67,11 +66,13 @@ pub trait Engine : Sync + Send {
// TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic
// from Spec into here and removing the Spec::builtins field.
/// TODO [Gav Wood] Please document me
/// Determine whether a particular address is a builtin contract.
fn is_builtin(&self, a: &Address) -> bool { self.spec().builtins.contains_key(a) }
/// TODO [Gav Wood] Please document me
/// Determine the code execution cost of the builtin contract with address `a`.
/// Panics if `is_builtin(a)` is not true.
fn cost_of_builtin(&self, a: &Address, input: &[u8]) -> U256 { self.spec().builtins.get(a).unwrap().cost(input.len()) }
/// TODO [Gav Wood] Please document me
/// Execution the builtin contract `a` on `input` and return `output`.
/// Panics if `is_builtin(a)` is not true.
fn execute_builtin(&self, a: &Address, input: &[u8], output: &mut [u8]) { self.spec().builtins.get(a).unwrap().execute(input, output); }
// TODO: sealing stuff - though might want to leave this for later.

View File

@ -24,13 +24,6 @@ pub struct EnvInfo {
pub gas_used: U256,
}
impl EnvInfo {
/// Create empty env_info initialized with zeros
pub fn new() -> EnvInfo {
EnvInfo::default()
}
}
impl Default for EnvInfo {
fn default() -> Self {
EnvInfo {

View File

@ -5,22 +5,22 @@ use header::BlockNumber;
use basic_types::LogBloom;
#[derive(Debug, PartialEq, Eq)]
/// TODO [Gav Wood] Please document me
/// Error indicating an expected value was not found.
pub struct Mismatch<T: fmt::Debug> {
/// TODO [Gav Wood] Please document me
/// Value expected.
pub expected: T,
/// TODO [Gav Wood] Please document me
/// Value found.
pub found: T,
}
#[derive(Debug, PartialEq, Eq)]
/// TODO [Gav Wood] Please document me
/// Error indicating value found is outside of a valid range.
pub struct OutOfBounds<T: fmt::Debug> {
/// TODO [Gav Wood] Please document me
/// Minimum allowed value.
pub min: Option<T>,
/// TODO [Gav Wood] Please document me
/// Maximum allowed value.
pub max: Option<T>,
/// TODO [Gav Wood] Please document me
/// Value found.
pub found: T,
}
@ -29,11 +29,10 @@ pub struct OutOfBounds<T: fmt::Debug> {
pub enum ExecutionError {
/// Returned when there gas paid for transaction execution is
/// lower than base gas required.
/// TODO [Gav Wood] Please document me
NotEnoughBaseGas {
/// TODO [Gav Wood] Please document me
/// Absolute minimum gas required.
required: U256,
/// TODO [Gav Wood] Please document me
/// Gas provided.
got: U256
},
/// Returned when block (gas_used + gas) > gas_limit.
@ -41,26 +40,26 @@ pub enum ExecutionError {
/// If gas =< gas_limit, upstream may try to execute the transaction
/// in next block.
BlockGasLimitReached {
/// TODO [Gav Wood] Please document me
/// Gas limit of block for transaction.
gas_limit: U256,
/// TODO [Gav Wood] Please document me
/// Gas used in block prior to transaction.
gas_used: U256,
/// TODO [Gav Wood] Please document me
/// Amount of gas in block.
gas: U256
},
/// Returned when transaction nonce does not match state nonce.
InvalidNonce {
/// TODO [Gav Wood] Please document me
/// Nonce expected.
expected: U256,
/// TODO [Gav Wood] Please document me
/// Nonce found.
got: U256
},
/// Returned when cost of transaction (value + gas_price * gas) exceeds
/// current sender balance.
NotEnoughCash {
/// TODO [Gav Wood] Please document me
/// Minimum required balance.
required: U512,
/// TODO [Gav Wood] Please document me
/// Actual balance.
got: U512
},
/// Returned when internal evm error occurs.
@ -68,76 +67,82 @@ pub enum ExecutionError {
}
#[derive(Debug)]
/// TODO [Gav Wood] Please document me
/// Errors concerning transaction proessing.
pub enum TransactionError {
/// TODO [Gav Wood] Please document me
/// Transaction's gas limit (aka gas) is invalid.
InvalidGasLimit(OutOfBounds<U256>),
}
#[derive(Debug, PartialEq, Eq)]
/// TODO [arkpar] Please document me
/// Errors concerning block processing.
pub enum BlockError {
/// TODO [Gav Wood] Please document me
/// Block has too many uncles.
TooManyUncles(OutOfBounds<usize>),
/// TODO [Gav Wood] Please document me
UncleWrongGeneration,
/// TODO [Gav Wood] Please document me
/// Extra data is of an invalid length.
ExtraDataOutOfBounds(OutOfBounds<usize>),
/// TODO [arkpar] Please document me
/// Seal is incorrect format.
InvalidSealArity(Mismatch<usize>),
/// TODO [arkpar] Please document me
/// Block has too much gas used.
TooMuchGasUsed(OutOfBounds<U256>),
/// TODO [arkpar] Please document me
/// Uncles hash in header is invalid.
InvalidUnclesHash(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// An uncle is from a generation too old.
UncleTooOld(OutOfBounds<BlockNumber>),
/// TODO [arkpar] Please document me
/// An uncle is from the same generation as the block.
UncleIsBrother(OutOfBounds<BlockNumber>),
/// TODO [arkpar] Please document me
/// An uncle is already in the chain.
UncleInChain(H256),
/// TODO [arkpar] Please document me
/// An uncle has a parent not in the chain.
UncleParentNotInChain(H256),
/// TODO [arkpar] Please document me
/// State root header field is invalid.
InvalidStateRoot(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// Gas used header field is invalid.
InvalidGasUsed(Mismatch<U256>),
/// TODO [arkpar] Please document me
/// Transactions root header field is invalid.
InvalidTransactionsRoot(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// Difficulty is out of range; this can be used as an looser error prior to getting a definitive
/// value for difficulty. This error needs only provide bounds of which it is out.
DifficultyOutOfBounds(OutOfBounds<U256>),
/// Difficulty header field is invalid; this is a strong error used after getting a definitive
/// value for difficulty (which is provided).
InvalidDifficulty(Mismatch<U256>),
/// TODO [arkpar] Please document me
/// Seal element of type H256 (max_hash for Ethash, but could be something else for
/// other seal engines) is out of bounds.
MismatchedH256SealElement(Mismatch<H256>),
/// Proof-of-work aspect of seal, which we assume is a 256-bit value, is invalid.
InvalidProofOfWork(OutOfBounds<U256>),
/// Gas limit header field is invalid.
InvalidGasLimit(OutOfBounds<U256>),
/// TODO [arkpar] Please document me
InvalidReceiptsStateRoot(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// Receipts trie root header field is invalid.
InvalidReceiptsRoot(Mismatch<H256>),
/// Timestamp header field is invalid.
InvalidTimestamp(OutOfBounds<u64>),
/// TODO [arkpar] Please document me
/// Log bloom header field is invalid.
InvalidLogBloom(Mismatch<LogBloom>),
/// TODO [arkpar] Please document me
InvalidEthashDifficulty(Mismatch<U256>),
/// TODO [arkpar] Please document me
InvalidBlockNonce(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// Parent hash field of header is invalid; this is an invalid error indicating a logic flaw in the codebase.
/// TODO: remove and favour an assert!/panic!.
InvalidParentHash(Mismatch<H256>),
/// TODO [arkpar] Please document me
/// Number field of header is invalid.
InvalidNumber(Mismatch<BlockNumber>),
/// Block number isn't sensible.
RidiculousNumber(OutOfBounds<BlockNumber>),
/// TODO [arkpar] Please document me
/// Parent given is unknown.
UnknownParent(H256),
/// TODO [Gav Wood] Please document me
/// Uncle parent given is unknown.
UnknownUncleParent(H256),
}
#[derive(Debug)]
/// TODO [arkpar] Please document me
/// Import to the block queue result
pub enum ImportError {
/// TODO [arkpar] Please document me
/// Bad block detected
Bad(Option<Error>),
/// TODO [arkpar] Please document me
/// Already in the block chain
AlreadyInChain,
/// TODO [arkpar] Please document me
/// Already in the block queue
AlreadyQueued,
/// Unknown parent
UnknownParent,
}
impl From<Error> for ImportError {
@ -152,15 +157,15 @@ pub type ImportResult = Result<H256, ImportError>;
#[derive(Debug)]
/// General error type which should be capable of representing all errors in ethcore.
pub enum Error {
/// TODO [Gav Wood] Please document me
/// Error concerning a utility.
Util(UtilError),
/// TODO [Gav Wood] Please document me
/// Error concerning block processing.
Block(BlockError),
/// TODO [Gav Wood] Please document me
/// Unknown engine given.
UnknownEngineName(String),
/// TODO [Gav Wood] Please document me
/// Error concerning EVM code execution.
Execution(ExecutionError),
/// TODO [Gav Wood] Please document me
/// Error concerning transaction processing.
Transaction(TransactionError),
}

View File

@ -1,22 +1,22 @@
use util::*;
#[inline]
/// TODO [debris] Please document me
/// 1 Ether in Wei
pub fn ether() -> U256 { U256::exp10(18) }
#[inline]
/// TODO [debris] Please document me
/// 1 Finney in Wei
pub fn finney() -> U256 { U256::exp10(15) }
#[inline]
/// TODO [debris] Please document me
/// 1 Szabo in Wei
pub fn szabo() -> U256 { U256::exp10(12) }
#[inline]
/// TODO [debris] Please document me
/// 1 Shannon in Wei
pub fn shannon() -> U256 { U256::exp10(9) }
#[inline]
/// TODO [debris] Please document me
/// 1 Wei in Wei
pub fn wei() -> U256 { U256::exp10(0) }

View File

@ -21,7 +21,7 @@ pub struct Ethash {
}
impl Ethash {
/// TODO [arkpar] Please document me
/// Create a new boxed instance of Ethash engine
pub fn new_boxed(spec: Spec) -> Box<Engine> {
Box::new(Ethash {
spec: spec,
@ -110,16 +110,18 @@ impl Engine for Ethash {
try!(UntrustedRlp::new(&header.seal[0]).as_val::<H256>());
try!(UntrustedRlp::new(&header.seal[1]).as_val::<H64>());
// TODO: consider removing these lines.
let min_difficulty = decode(self.spec().engine_params.get("minimumDifficulty").unwrap());
if header.difficulty < min_difficulty {
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: min_difficulty, found: header.difficulty })))
return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty })))
}
let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(quick_get_difficulty(
&Ethash::to_ethash(header.bare_hash()),
header.nonce().low_u64(),
&Ethash::to_ethash(header.mix_hash()))));
if difficulty < header.difficulty {
return Err(From::from(BlockError::InvalidEthashDifficulty(Mismatch { expected: header.difficulty, found: difficulty })));
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty })));
}
Ok(())
}
@ -129,10 +131,10 @@ impl Engine for Ethash {
let mix = Ethash::from_ethash(result.mix_hash);
let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value));
if mix != header.mix_hash() {
return Err(From::from(BlockError::InvalidBlockNonce(Mismatch { expected: mix, found: header.mix_hash() })));
return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: header.mix_hash() })));
}
if difficulty < header.difficulty {
return Err(From::from(BlockError::InvalidEthashDifficulty(Mismatch { expected: header.difficulty, found: difficulty })));
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty })));
}
Ok(())
}

View File

@ -3,9 +3,9 @@
//! Contains all Ethereum network specific stuff, such as denominations and
//! consensus specifications.
/// TODO [Gav Wood] Please document me
/// Export the ethash module.
pub mod ethash;
/// TODO [Gav Wood] Please document me
/// Export the denominations module.
pub mod denominations;
pub use self::ethash::*;

View File

@ -15,35 +15,35 @@ pub enum Error {
/// `BadJumpDestination` is returned when execution tried to move
/// to position that wasn't marked with JUMPDEST instruction
BadJumpDestination {
/// TODO [Tomusdrw] Please document me
/// Position the code tried to jump to.
destination: usize
},
/// `BadInstructions` is returned when given instruction is not supported
BadInstruction {
/// TODO [Tomusdrw] Please document me
/// Unrecognized opcode
instruction: u8,
},
/// `StackUnderflow` when there is not enough stack elements to execute instruction
/// First parameter says how many elements were needed and the second how many were actually on Stack
StackUnderflow {
/// TODO [Tomusdrw] Please document me
/// Invoked instruction
instruction: &'static str,
/// TODO [Tomusdrw] Please document me
/// How many stack elements was requested by instruction
wanted: usize,
/// TODO [Tomusdrw] Please document me
/// How many elements were on stack
on_stack: usize
},
/// When execution would exceed defined Stack Limit
OutOfStack {
/// TODO [Tomusdrw] Please document me
/// Invoked instruction
instruction: &'static str,
/// TODO [Tomusdrw] Please document me
/// How many stack elements instruction wanted to push
wanted: usize,
/// TODO [Tomusdrw] Please document me
/// What was the stack limit
limit: usize
},
/// Returned on evm internal error. Should never be ignored during development.
/// Likely to cause consensus issues.
#[allow(dead_code)] // created only by jit
Internal,
}

View File

@ -1,25 +1,39 @@
//! Evm factory.
//!
//! TODO: consider spliting it into two separate files.
#[cfg(test)]
use std::fmt;
use evm::Evm;
#[derive(Clone)]
/// TODO [Tomusdrw] Please document me
/// Type of EVM to use.
pub enum VMType {
/// TODO [Tomusdrw] Please document me
/// JIT EVM
#[cfg(feature="jit")]
Jit,
/// TODO [Tomusdrw] Please document me
/// RUST EVM
Interpreter
}
#[cfg(test)]
impl fmt::Display for VMType {
#[cfg(feature="jit")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Jit => "JIT",
VMType::Interpreter => "INT"
})
}
#[cfg(not(feature="jit"))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Interpreter => "INT"
})
}
}
#[cfg(test)]
#[cfg(feature = "json-tests")]
impl VMType {
/// Return all possible VMs (JIT, Interpreter)
#[cfg(feature="jit")]
@ -41,10 +55,11 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
#[cfg(feature="jit")]
pub fn create(&self) -> Box<Evm> {
match self.evm {
VMType::Jit => {
Factory::jit()
Box::new(super::jit::JitEvm)
},
VMType::Interpreter => {
Box::new(super::interpreter::Interpreter)
@ -52,22 +67,23 @@ impl Factory {
}
}
/// Create fresh instance of VM
#[cfg(not(feature="jit"))]
pub fn create(&self) -> Box<Evm> {
match self.evm {
VMType::Interpreter => {
Box::new(super::interpreter::Interpreter)
}
}
}
/// Create new instance of specific `VMType` factory
#[cfg(test)]
pub fn new(evm: VMType) -> Factory {
Factory {
evm: evm
}
}
#[cfg(feature = "jit")]
fn jit() -> Box<Evm> {
Box::new(super::jit::JitEvm)
}
#[cfg(not(feature = "jit"))]
fn jit() -> Box<Evm> {
unimplemented!()
}
}
impl Default for Factory {
/// Returns jitvm factory
@ -95,6 +111,18 @@ fn test_create_vm() {
/// Create tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test(
(ignorejit => $name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit));
}
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter));
}
};
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]

View File

@ -1,11 +1,10 @@
///! Rust VM implementation
use common::*;
use evm;
use super::instructions as instructions;
use super::instructions::Instruction;
use std::marker::Copy;
use evm::{MessageCallResult, ContractCreateResult};
use evm::{self, MessageCallResult, ContractCreateResult};
#[cfg(not(feature = "evm-debug"))]
macro_rules! evm_debug {

View File

@ -2,7 +2,6 @@
pub mod ext;
pub mod evm;
/// TODO [Tomusdrw] Please document me
pub mod interpreter;
#[macro_use]
pub mod factory;

View File

@ -1,25 +1,45 @@
use common::*;
use evm;
use evm::{Ext, Schedule, Factory, VMType, ContractCreateResult, MessageCallResult};
use std::fmt::Debug;
struct FakeLogEntry {
topics: Vec<H256>,
data: Bytes
}
#[derive(PartialEq, Eq, Hash, Debug)]
enum FakeCallType {
CALL, CREATE
}
#[derive(PartialEq, Eq, Hash, Debug)]
struct FakeCall {
call_type: FakeCallType,
gas: U256,
sender_address: Option<Address>,
receive_address: Option<Address>,
value: Option<U256>,
data: Bytes,
code_address: Option<Address>
}
/// Fake externalities test structure.
///
/// Can't do recursive calls.
#[derive(Default)]
struct FakeExt {
sstore_clears: usize,
depth: usize,
store: HashMap<H256, H256>,
_balances: HashMap<Address, U256>,
blockhashes: HashMap<U256, H256>,
codes: HashMap<Address, Bytes>,
logs: Vec<FakeLogEntry>,
_suicides: HashSet<Address>,
info: EnvInfo,
schedule: Schedule
schedule: Schedule,
balances: HashMap<Address, U256>,
calls: HashSet<FakeCall>
}
impl FakeExt {
@ -43,31 +63,50 @@ impl Ext for FakeExt {
self.store.insert(key, value);
}
fn exists(&self, _address: &Address) -> bool {
unimplemented!();
fn exists(&self, address: &Address) -> bool {
self.balances.contains_key(address)
}
fn balance(&self, _address: &Address) -> U256 {
unimplemented!();
fn balance(&self, address: &Address) -> U256 {
self.balances.get(address).unwrap().clone()
}
fn blockhash(&self, number: &U256) -> H256 {
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
}
fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8]) -> ContractCreateResult {
unimplemented!();
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::CREATE,
gas: gas.clone(),
sender_address: None,
receive_address: None,
value: Some(value.clone()),
data: code.to_vec(),
code_address: None
});
ContractCreateResult::Failed
}
fn call(&mut self,
_gas: &U256,
_sender_address: &Address,
_receive_address: &Address,
_value: Option<U256>,
_data: &[u8],
_code_address: &Address,
gas: &U256,
sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
code_address: &Address,
_output: &mut [u8]) -> MessageCallResult {
unimplemented!();
self.calls.insert(FakeCall {
call_type: FakeCallType::CALL,
gas: gas.clone(),
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())
}
fn extcode(&self, address: &Address) -> Bytes {
@ -98,11 +137,11 @@ impl Ext for FakeExt {
}
fn depth(&self) -> usize {
unimplemented!();
self.depth
}
fn inc_sstore_clears(&mut self) {
unimplemented!();
self.sstore_clears += 1;
}
}
@ -150,7 +189,7 @@ fn test_add(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_988));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap());
assert_store(&ext, 0, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
}
evm_test!{test_sha3: test_sha3_jit, test_sha3_int}
@ -170,7 +209,7 @@ fn test_sha3(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_961));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap());
assert_store(&ext, 0, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
}
evm_test!{test_address: test_address_jit, test_address_int}
@ -190,7 +229,7 @@ fn test_address(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap());
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
}
evm_test!{test_origin: test_origin_jit, test_origin_int}
@ -212,11 +251,10 @@ fn test_origin(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap());
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
}
// TODO [todr] Fails with Signal 11 on JIT
evm_test!{test_sender: test_sender_jit, test_sender_int}
evm_test!{ignorejit => test_sender: test_sender_jit, test_sender_int}
fn test_sender(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@ -235,7 +273,7 @@ fn test_sender(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap());
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
}
evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int}
@ -270,7 +308,7 @@ fn test_extcodecopy(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_935));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("6005600055000000000000000000000000000000000000000000000000000000").unwrap());
assert_store(&ext, 0, "6005600055000000000000000000000000000000000000000000000000000000");
}
evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int}
@ -328,7 +366,7 @@ fn test_log_sender(factory: super::Factory) {
assert_eq!(ext.logs[0].data, "ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
}
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
evm_test!{ignorejit => test_blockhash: test_blockhash_jit, test_blockhash_int}
fn test_blockhash(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600040600055".from_hex().unwrap();
@ -369,7 +407,7 @@ fn test_calldataload(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_991));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap());
assert_store(&ext, 0, "23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23");
}
@ -390,7 +428,7 @@ fn test_author(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap());
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
}
evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int}
@ -410,7 +448,7 @@ fn test_timestamp(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap());
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_number: test_number_jit, test_number_int}
@ -430,7 +468,7 @@ fn test_number(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap());
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int}
@ -450,7 +488,7 @@ fn test_difficulty(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap());
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int}
@ -470,6 +508,421 @@ fn test_gas_limit(factory: super::Factory) {
};
assert_eq!(gas_left, U256::from(79_995));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap());
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_mul: test_mul_jit, test_mul_int}
fn test_mul(factory: super::Factory) {
let code = "65012365124623626543219002600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383");
assert_eq!(gas_left, U256::from(79_983));
}
evm_test!{test_sub: test_sub_jit, test_sub_int}
fn test_sub(factory: super::Factory) {
let code = "65012365124623626543219003600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302");
assert_eq!(gas_left, U256::from(79_985));
}
evm_test!{test_div: test_div_jit, test_div_int}
fn test_div(factory: super::Factory) {
let code = "65012365124623626543219004600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
assert_eq!(gas_left, U256::from(79_983));
}
evm_test!{test_div_zero: test_div_zero_jit, test_div_zero_int}
fn test_div_zero(factory: super::Factory) {
let code = "6501236512462360009004600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
assert_eq!(gas_left, U256::from(94_983));
}
evm_test!{test_mod: test_mod_jit, test_mod_int}
fn test_mod(factory: super::Factory) {
let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000");
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_smod: test_smod_jit, test_smod_int}
fn test_smod(factory: super::Factory) {
let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000");
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_sdiv: test_sdiv_jit, test_sdiv_int}
fn test_sdiv(factory: super::Factory) {
let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000");
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_exp: test_exp_jit, test_exp_int}
fn test_exp(factory: super::Factory) {
let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000012365124623");
assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000001");
assert_eq!(gas_left, U256::from(39_923));
}
evm_test!{test_comparison: test_comparison_jit, test_comparison_int}
fn test_comparison(factory: super::Factory) {
let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000001");
assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000000");
assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000001");
assert_eq!(gas_left, U256::from(49_952));
}
evm_test!{test_signed_comparison: test_signed_comparison_jit, test_signed_comparison_int}
fn test_signed_comparison(factory: super::Factory) {
let code = "60106000036010818112600055136001556010601060000381811260025513600355".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000001");
assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000001");
assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000000");
assert_eq!(gas_left, U256::from(49_940));
}
evm_test!{test_bitops: test_bitops_jit, test_bitops_int}
fn test_bitops(factory: super::Factory) {
let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(150_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000fff");
assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000f0f");
assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000001");
assert_store(&ext, 4, "0000000000000000000000000000000000000000000000000000000000000000");
assert_store(&ext, 5, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
assert_eq!(gas_left, U256::from(44_937));
}
evm_test!{test_addmod_mulmod: test_addmod_mulmod_jit, test_addmod_mulmod_int}
fn test_addmod_mulmod(factory: super::Factory) {
let code = "60ff60f060108282820860005509600155600060f0601082828208196002550919600355".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001");
assert_store(&ext, 1, "000000000000000000000000000000000000000000000000000000000000000f");
assert_store(&ext, 2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
assert_store(&ext, 3, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
assert_eq!(gas_left, U256::from(19_914));
}
evm_test!{test_byte: test_byte_jit, test_byte_int}
fn test_byte(factory: super::Factory) {
let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
assert_store(&ext, 1, "00000000000000000000000000000000000000000000000000000000000000ff");
assert_eq!(gas_left, U256::from(74_976));
}
evm_test!{test_signextend: test_signextend_jit, test_signextend_int}
fn test_signextend(factory: super::Factory) {
let code = "610fff60020b60005560ff60200b600155".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff");
assert_store(&ext, 1, "00000000000000000000000000000000000000000000000000000000000000ff");
assert_eq!(gas_left, U256::from(59_972));
}
#[test] // JIT just returns out of gas
fn test_badinstruction_int() {
let factory = super::Factory::new(VMType::Interpreter);
let code = "af".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let err = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap_err()
};
match err {
evm::Error::BadInstruction { instruction: 0xaf } => (),
_ => assert!(false, "Expected bad instruction")
}
}
evm_test!{test_pop: test_pop_jit, test_pop_int}
fn test_pop(factory: super::Factory) {
let code = "60f060aa50600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
assert_eq!(gas_left, U256::from(79_989));
}
evm_test!{test_extops: test_extops_jit, test_extops_int}
fn test_extops(factory: super::Factory) {
let code = "5a6001555836553a600255386003553460045560016001526016590454600555".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(150_000);
params.gas_price = U256::from(0x32);
params.value = ActionValue::Transfer(U256::from(0x99));
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000004"); // PC / CALLDATASIZE
assert_store(&ext, 1, "00000000000000000000000000000000000000000000000000000000000249ee"); // GAS
assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000032"); // GASPRICE
assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000020"); // CODESIZE
assert_store(&ext, 4, "0000000000000000000000000000000000000000000000000000000000000099"); // CALLVALUE
assert_store(&ext, 5, "0000000000000000000000000000000000000000000000000000000000000032");
assert_eq!(gas_left, U256::from(29_898));
}
evm_test!{test_jumps: test_jumps_jit, test_jumps_int}
fn test_jumps(factory: super::Factory) {
let code = "600160015560066000555b60016000540380806000551560245760015402600155600a565b".from_hex().unwrap();
let mut params = ActionParams::default();
params.gas = U256::from(150_000);
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_eq!(ext.sstore_clears, 1);
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); // 5!
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000078"); // 5!
assert_eq!(gas_left, U256::from(54_117));
}
evm_test!{test_calls: test_calls_jit, test_calls_int}
fn test_calls(factory: super::Factory) {
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
let address = Address::from(0x155);
let code_address = Address::from(0x998);
let mut params = ActionParams::default();
params.gas = U256::from(150_000);
params.code = Some(code);
params.address = address.clone();
let mut ext = FakeExt::new();
ext.balances = {
let mut s = HashMap::new();
s.insert(params.address.clone(), params.gas.clone());
s
};
let gas_left = {
let vm = factory.create();
vm.exec(params, &mut ext).unwrap()
};
assert_set_contains(&ext.calls, &FakeCall {
call_type: FakeCallType::CALL,
gas: U256::from(2556),
sender_address: Some(address.clone()),
receive_address: Some(code_address.clone()),
value: Some(U256::from(0x50)),
data: vec!(),
code_address: Some(code_address.clone())
});
assert_set_contains(&ext.calls, &FakeCall {
call_type: FakeCallType::CALL,
gas: U256::from(2556),
sender_address: Some(address.clone()),
receive_address: Some(address.clone()),
value: Some(U256::from(0x50)),
data: vec!(),
code_address: Some(code_address.clone())
});
assert_eq!(gas_left, U256::from(91_405));
assert_eq!(ext.calls.len(), 2);
}
fn assert_set_contains<T : Debug + Eq + PartialEq + Hash>(set: &HashSet<T>, val: &T) {
let contains = set.contains(val);
if !contains {
println!("Set: {:?}", set);
println!("Elem: {:?}", val);
}
assert!(contains, "Element not found in HashSet");
}
fn assert_store(ext: &FakeExt, pos: u64, val: &str) {
assert_eq!(ext.store.get(&H256::from(pos)).unwrap(), &H256::from_str(val).unwrap());
}

View File

@ -129,7 +129,7 @@ impl<'a> Executive<'a> {
let mut substate = Substate::new();
let res = match *t.action() {
let res = match t.action {
Action::Create => {
let new_address = contract_address(&sender, &nonce);
let params = ActionParams {
@ -399,7 +399,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(0x100u64));
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
@ -458,7 +458,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
@ -512,7 +512,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
@ -564,7 +564,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(1024, factory);
let mut substate = Substate::new();
@ -624,7 +624,7 @@ mod tests {
state.init_code(&address_b, code_b.clone());
state.add_balance(&sender, &U256::from(100_000));
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
@ -668,7 +668,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.init_code(&address, code.clone());
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
@ -694,7 +694,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(18));
let mut info = EnvInfo::new();
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0, factory);
@ -721,7 +721,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
let mut info = EnvInfo::new();
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0, factory);
@ -746,7 +746,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(17));
let mut info = EnvInfo::new();
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0, factory);
@ -772,7 +772,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(17));
let mut info = EnvInfo::new();
let mut info = EnvInfo::default();
info.gas_used = U256::from(20_000);
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0, factory);
@ -799,7 +799,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(100_017));
let mut info = EnvInfo::new();
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0, factory);
@ -833,7 +833,7 @@ mod tests {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap());
let info = EnvInfo::new();
let info = EnvInfo::default();
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();

View File

@ -1,3 +1,5 @@
//! Blockchain DB extras.
use util::*;
use header::BlockNumber;
use rocksdb::{DB, Writable};
@ -5,21 +7,21 @@ use rocksdb::{DB, Writable};
/// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
pub enum ExtrasIndex {
/// TODO [debris] Please document me
/// Block details index
BlockDetails = 0,
/// TODO [debris] Please document me
/// Block hash index
BlockHash = 1,
/// TODO [debris] Please document me
/// Transaction address index
TransactionAddress = 2,
/// TODO [debris] Please document me
/// Block log blooms index
BlockLogBlooms = 3,
/// TODO [debris] Please document me
/// Block blooms index
BlocksBlooms = 4
}
/// trait used to write Extras data to db
pub trait ExtrasWritable {
/// TODO [debris] Please document me
/// Write extra data to db
fn put_extras<K, T>(&self, hash: &K, value: &T) where
T: ExtrasIndexable + Encodable,
K: ExtrasSliceConvertable;
@ -27,12 +29,12 @@ pub trait ExtrasWritable {
/// trait used to read Extras data from db
pub trait ExtrasReadable {
/// TODO [debris] Please document me
/// Read extra data from db
fn get_extras<K, T>(&self, hash: &K) -> Option<T> where
T: ExtrasIndexable + Decodable,
K: ExtrasSliceConvertable;
/// TODO [debris] Please document me
/// Check if extra data exists in the db
fn extras_exists<K, T>(&self, hash: &K) -> bool where
T: ExtrasIndexable,
K: ExtrasSliceConvertable;
@ -66,9 +68,9 @@ impl ExtrasReadable for DB {
/// Implementations should convert arbitrary type to database key slice
pub trait ExtrasSliceConvertable {
/// TODO [Gav Wood] Please document me
/// Convert self, with `i` (the index), to a 264-bit extras DB key.
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
/// TODO [debris] Please document me
/// Interpret self as a 256-bit hash, if natively `H256`.
fn as_h256(&self) -> Option<&H256> { None }
}
@ -96,7 +98,7 @@ impl ExtrasSliceConvertable for BlockNumber {
/// Types implementing this trait can be indexed in extras database
pub trait ExtrasIndexable {
/// TODO [debris] Please document me
/// Returns this data index
fn extras_index() -> ExtrasIndex;
}
@ -109,13 +111,13 @@ impl ExtrasIndexable for H256 {
/// Familial details concerning a block
#[derive(Debug, Clone)]
pub struct BlockDetails {
/// TODO [debris] Please document me
/// Block number
pub number: BlockNumber,
/// TODO [debris] Please document me
/// Total difficulty of the block and all its parents
pub total_difficulty: U256,
/// TODO [debris] Please document me
/// Parent block hash
pub parent: H256,
/// TODO [debris] Please document me
/// List of children block hashes
pub children: Vec<H256>
}
@ -157,7 +159,7 @@ impl Encodable for BlockDetails {
/// Log blooms of certain block
#[derive(Clone)]
pub struct BlockLogBlooms {
/// TODO [debris] Please document me
/// List of log blooms for the block
pub blooms: Vec<H2048>
}
@ -191,7 +193,7 @@ impl Encodable for BlockLogBlooms {
/// Neighboring log blooms on certain level
pub struct BlocksBlooms {
/// TODO [debris] Please document me
/// List of block blooms.
pub blooms: [H2048; 16]
}
@ -239,9 +241,9 @@ impl Encodable for BlocksBlooms {
/// Represents address of certain transaction within block
#[derive(Clone)]
pub struct TransactionAddress {
/// TODO [debris] Please document me
/// Block hash
pub block_hash: H256,
/// TODO [debris] Please document me
/// Transaction index within the block
pub index: u64
}

View File

@ -1,3 +1,5 @@
//! Block header.
use util::*;
use basic_types::*;
use time::now_utc;
@ -11,50 +13,49 @@ pub type BlockNumber = u64;
/// which is non-specific.
///
/// Doesn't do all that much on its own.
#[derive(Default, Debug, Clone)]
#[derive(Debug, Clone)]
pub struct Header {
// TODO: make all private.
/// TODO [Gav Wood] Please document me
/// Parent hash.
pub parent_hash: H256,
/// TODO [arkpar] Please document me
/// Block timestamp.
pub timestamp: u64,
/// TODO [debris] Please document me
/// Block number.
pub number: BlockNumber,
/// TODO [Gav Wood] Please document me
/// Block author.
pub author: Address,
/// TODO [debris] Please document me
/// Transactions root.
pub transactions_root: H256,
/// TODO [debris] Please document me
/// Block uncles hash.
pub uncles_hash: H256,
/// TODO [Gav Wood] Please document me
/// Block extra data.
pub extra_data: Bytes,
/// TODO [debris] Please document me
/// State root.
pub state_root: H256,
/// TODO [debris] Please document me
/// Block receipts root.
pub receipts_root: H256,
/// TODO [debris] Please document me
/// Block bloom.
pub log_bloom: LogBloom,
/// TODO [debris] Please document me
/// Gas used for contracts execution.
pub gas_used: U256,
/// TODO [Gav Wood] Please document me
/// Block gas limit.
pub gas_limit: U256,
/// TODO [debris] Please document me
/// Block difficulty.
pub difficulty: U256,
/// TODO [arkpar] Please document me
/// Block seal.
pub seal: Vec<Bytes>,
/// TODO [arkpar] Please document me
/// The memoized hash of the RLP representation *including* the seal fields.
pub hash: RefCell<Option<H256>>,
/// TODO [Gav Wood] Please document me
/// The memoized hash of the RLP representation *without* the seal fields.
pub bare_hash: RefCell<Option<H256>>,
}
impl Header {
/// Create a new, default-valued, header.
pub fn new() -> Header {
impl Default for Header {
fn default() -> Self {
Header {
parent_hash: ZERO_H256.clone(),
timestamp: 0,
@ -77,51 +78,58 @@ impl Header {
bare_hash: RefCell::new(None),
}
}
}
/// TODO [Gav Wood] Please document me
impl Header {
/// Create a new, default-valued, header.
pub fn new() -> Self {
Self::default()
}
/// Get the number field of the header.
pub fn number(&self) -> BlockNumber { self.number }
/// TODO [Gav Wood] Please document me
/// Get the timestamp field of the header.
pub fn timestamp(&self) -> u64 { self.timestamp }
/// TODO [Gav Wood] Please document me
/// Get the author field of the header.
pub fn author(&self) -> &Address { &self.author }
/// TODO [Gav Wood] Please document me
/// Get the extra data field of the header.
pub fn extra_data(&self) -> &Bytes { &self.extra_data }
/// TODO [Gav Wood] Please document me
/// Get the state root field of the header.
pub fn state_root(&self) -> &H256 { &self.state_root }
/// TODO [Gav Wood] Please document me
/// Get the receipts root field of the header.
pub fn receipts_root(&self) -> &H256 { &self.receipts_root }
/// TODO [Gav Wood] Please document me
/// Get the gas limit field of the header.
pub fn gas_limit(&self) -> &U256 { &self.gas_limit }
/// TODO [Gav Wood] Please document me
/// Get the difficulty field of the header.
pub fn difficulty(&self) -> &U256 { &self.difficulty }
/// TODO [Gav Wood] Please document me
/// Get the seal field of the header.
pub fn seal(&self) -> &Vec<Bytes> { &self.seal }
// TODO: seal_at, set_seal_at &c.
/// TODO [Gav Wood] Please document me
/// Set the number field of the header.
pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the timestamp field of the header.
pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the timestamp field of the header to the current time.
pub fn set_timestamp_now(&mut self) { self.timestamp = now_utc().to_timespec().sec as u64; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the author field of the header.
pub fn set_author(&mut self, a: Address) { if a != self.author { self.author = a; self.note_dirty(); } }
/// TODO [Gav Wood] Please document me
/// Set the extra data field of the header.
pub fn set_extra_data(&mut self, a: Bytes) { if a != self.extra_data { self.extra_data = a; self.note_dirty(); } }
/// TODO [Gav Wood] Please document me
/// Set the gas used field of the header.
pub fn set_gas_used(&mut self, a: U256) { self.gas_used = a; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the gas limit field of the header.
pub fn set_gas_limit(&mut self, a: U256) { self.gas_limit = a; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the difficulty field of the header.
pub fn set_difficulty(&mut self, a: U256) { self.difficulty = a; self.note_dirty(); }
/// TODO [Gav Wood] Please document me
/// Set the seal field of the header.
pub fn set_seal(&mut self, a: Vec<Bytes>) { self.seal = a; self.note_dirty(); }
/// Get the hash of this header (sha3 of the RLP).
@ -155,7 +163,7 @@ impl Header {
}
// TODO: make these functions traity
/// TODO [Gav Wood] Please document me
/// Place this header into an RLP stream `s`, optionally `with_seal`.
pub fn stream_rlp(&self, s: &mut RlpStream, with_seal: Seal) {
s.begin_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 0 });
s.append(&self.parent_hash);
@ -178,14 +186,14 @@ impl Header {
}
}
/// TODO [Gav Wood] Please document me
/// Get the RLP of this header, optionally `with_seal`.
pub fn rlp(&self, with_seal: Seal) -> Bytes {
let mut s = RlpStream::new();
self.stream_rlp(&mut s, with_seal);
s.out()
}
/// TODO [debris] Please document me
/// Get the SHA3 (Keccak) of this header, optionally `with_seal`.
pub fn rlp_sha3(&self, with_seal: Seal) -> H256 { self.rlp(with_seal).sha3() }
}

View File

@ -3,7 +3,7 @@ use client::{BlockChainClient,Client};
use pod_state::*;
use block::Block;
use ethereum;
use super::helpers::*;
use tests::helpers::*;
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
init_log();
@ -15,12 +15,12 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
{
let mut fail_unless = |cond: bool| if !cond && !fail {
failed.push(name.clone());
flush(format!("FAIL\n"));
flushln!("FAIL");
fail = true;
true
} else {false};
flush(format!(" - {}...", name));
flush!(" - {}...", name);
let blocks: Vec<(Bytes, bool)> = test["blocks"].as_array().unwrap().iter().map(|e| (xjson!(&e["rlp"]), e.find("blockHeader").is_some())).collect();
let mut spec = match era {
@ -50,7 +50,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
}
}
if !fail {
flush(format!("ok\n"));
flushln!("ok");
}
}
println!("!!! {:?} tests from failed.", failed.len());

View File

@ -1,6 +1,6 @@
use client::{BlockChainClient,Client};
use super::test_common::*;
use super::helpers::*;
use tests::helpers::*;
#[test]
fn created() {

View File

@ -1,6 +1,6 @@
use super::test_common::*;
use super::helpers::*;
use super::chain::json_chain_test;
use tests::helpers::*;
fn do_json_test(json_data: &[u8]) -> Vec<String> {
json_chain_test(json_data, ChainEra::Homestead)

View File

@ -1,5 +1,5 @@
use super::test_common::*;
use super::helpers::*;
use tests::helpers::*;
use super::state::json_chain_test;
fn do_json_test(json_data: &[u8]) -> Vec<String> {

View File

@ -0,0 +1,10 @@
#[macro_use]
mod test_common;
mod transaction;
mod executive;
mod state;
mod client;
mod chain;
mod homestead_state;
mod homestead_chain;

View File

@ -1,5 +1,5 @@
use super::test_common::*;
use super::helpers::*;
use tests::helpers::*;
use pod_state::*;
use state_diff::*;
use ethereum;
@ -19,19 +19,19 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
ChainEra::Homestead => ethereum::new_homestead_test(),
}.to_engine().unwrap();
flush(format!("\n"));
flushln!("");
for (name, test) in json.as_object().unwrap() {
let mut fail = false;
{
let mut fail_unless = |cond: bool| if !cond && !fail {
failed.push(name.clone());
flush(format!("FAIL\n"));
flushln!("FAIL");
fail = true;
true
} else {false};
flush(format!(" - {}...", name));
flush!(" - {}...", name);
let t = Transaction::from_json(&test["transaction"]);
let env = EnvInfo::from_json(&test["env"]);
@ -73,7 +73,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
}
}
if !fail {
flush(format!("ok\n"));
flushln!("ok");
}
// TODO: Add extra APIs for output
//if fail_unless(out == r.)

View File

@ -12,7 +12,6 @@ macro_rules! declare_test {
#[ignore]
#[test]
#[allow(non_snake_case)]
#[cfg(feature="json-tests")]
fn $id() {
test!($name);
}
@ -21,7 +20,6 @@ macro_rules! declare_test {
#[cfg(feature = "test-heavy")]
#[test]
#[allow(non_snake_case)]
#[cfg(feature="json-tests")]
fn $id() {
test!($name);
}
@ -29,7 +27,6 @@ macro_rules! declare_test {
($id: ident, $name: expr) => {
#[test]
#[allow(non_snake_case)]
#[cfg(feature="json-tests")]
fn $id() {
test!($name);
}

View File

@ -2,157 +2,113 @@
#![feature(cell_extras)]
#![feature(augmented_assignments)]
#![feature(plugin)]
//#![plugin(interpolate_idents)]
#![plugin(clippy)]
#![allow(needless_range_loop, match_bool)]
//! Ethcore's ethereum implementation
//! Ethcore library
//!
//! ### Rust version
//! - beta
//! ### Rust version:
//! - nightly
//!
//! ### Supported platforms:
//! - OSX
//! - Linux/Ubuntu
//! - Linux
//!
//! ### Dependencies:
//! - RocksDB 3.13
//! - LLVM 3.7 (optional, required for `jit`)
//! - evmjit (optional, required for `jit`)
//! ### Building:
//!
//! ### Dependencies Installation
//! - Ubuntu 14.04 and later:
//!
//! - OSX
//!
//! - rocksdb
//! ```bash
//! # install rocksdb
//! add-apt-repository "deb http://ppa.launchpad.net/giskou/librocksdb/ubuntu trusty main"
//! apt-get update
//! apt-get install -y --force-yes librocksdb
//!
//! # install multirust
//! curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes
//!
//! # install nightly and make it default
//! multirust update nightly && multirust default nightly
//!
//! # export rust LIBRARY_PATH
//! export LIBRARY_PATH=/usr/local/lib
//!
//! # download and build parity
//! git clone https://github.com/ethcore/parity
//! cd parity
//! cargo build --release
//! ```
//!
//! - OSX:
//!
//! ```bash
//! # install rocksdb && multirust
//! brew update
//! brew install rocksdb
//! brew install multirust
//!
//! # install nightly and make it default
//! multirust update nightly && multirust default nightly
//!
//! # export rust LIBRARY_PATH
//! export LIBRARY_PATH=/usr/local/lib
//!
//! # download and build parity
//! git clone https://github.com/ethcore/parity
//! cd parity
//! cargo build --release
//! ```
//!
//! - llvm
//!
//! - download llvm 3.7 from http://llvm.org/apt/
//!
//! ```bash
//! cd llvm-3.7.0.src
//! mkdir build && cd $_
//! cmake -G "Unix Makefiles" .. -DCMAKE_C_FLAGS_RELEASE= -DCMAKE_CXX_FLAGS_RELEASE= -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/llvm/3.7 -DCMAKE_BUILD_TYPE=Release
//! make && make install
//! ```
//! - evmjit
//!
//! - download from https://github.com/debris/evmjit
//!
//! ```bash
//! cd evmjit
//! mkdir build && cd $_
//! cmake -DLLVM_DIR=/usr/local/lib/llvm-3.7/share/llvm/cmake ..
//! make && make install
//! ```
//!
//! - Linux/Ubuntu
//!
//! - rocksdb
//!
//! ```bash
//! wget https://github.com/facebook/rocksdb/archive/rocksdb-3.13.tar.gz
//! tar xvf rocksdb-3.13.tar.gz && cd rocksdb-rocksdb-3.13 && make shared_lib
//! sudo make install
//! ```
//!
//! - llvm
//!
//! - install using packages from http://llvm.org/apt/
//!
//! - evmjit
//!
//! - download from https://github.com/debris/evmjit
//!
//! ```bash
//! cd evmjit
//! mkdir build && cd $_
//! cmake .. && make
//! sudo make install
//! sudo ldconfig
//! ```
#[macro_use]
extern crate log;
#[macro_use] extern crate log;
#[macro_use] extern crate ethcore_util as util;
#[macro_use] extern crate lazy_static;
extern crate rustc_serialize;
extern crate flate2;
extern crate rocksdb;
extern crate heapsize;
extern crate crypto;
extern crate time;
extern crate env_logger;
extern crate num_cpus;
#[cfg(feature = "jit" )]
extern crate evmjit;
#[macro_use]
extern crate ethcore_util as util;
extern crate crossbeam;
#[macro_use]
extern crate lazy_static;
// NOTE: Add doc parser exception for these pub declarations.
#[cfg(feature = "jit" )] extern crate evmjit;
/// TODO [Gav Wood] Please document me
pub mod common;
/// TODO [Tomusdrw] Please document me
pub mod basic_types;
#[macro_use]
pub mod evm;
pub mod block;
pub mod blockchain;
pub mod block_queue;
pub mod client;
pub mod error;
/// TODO [Gav Wood] Please document me
pub mod log_entry;
/// TODO [Gav Wood] Please document me
pub mod env_info;
/// TODO [Gav Wood] Please document me
pub mod pod_account;
/// TODO [Gav Wood] Please document me
pub mod pod_state;
/// TODO [Gav Wood] Please document me
pub mod account_diff;
/// TODO [Gav Wood] Please document me
pub mod state_diff;
/// TODO [Gav Wood] Please document me
pub mod engine;
/// TODO [Gav Wood] Please document me
pub mod state;
/// TODO [Gav Wood] Please document me
pub mod account;
pub mod action_params;
/// TODO [debris] Please document me
pub mod ethereum;
pub mod header;
/// TODO [Gav Wood] Please document me
pub mod transaction;
/// TODO [Gav Wood] Please document me
pub mod receipt;
/// TODO [Gav Wood] Please document me
pub mod null_engine;
/// TODO [Gav Wood] Please document me
pub mod builtin;
/// TODO [debris] Please document me
pub mod service;
pub mod spec;
pub mod views;
pub mod blockchain;
/// TODO [Gav Wood] Please document me
pub mod extras;
/// TODO [arkpar] Please document me
pub mod substate;
/// TODO [Gav Wood] Please document me
pub mod service;
pub mod executive;
pub mod externalities;
mod common;
mod basic_types;
#[macro_use] mod evm;
mod log_entry;
mod env_info;
mod pod_account;
mod pod_state;
mod account_diff;
mod state_diff;
mod engine;
mod state;
mod account;
mod action_params;
mod transaction;
mod receipt;
mod null_engine;
mod builtin;
mod extras;
mod substate;
mod executive;
mod externalities;
mod verification;
#[cfg(test)]
mod tests;
/// TODO [arkpar] Please document me
pub mod client;
/// TODO [arkpar] Please document me
pub mod block;
/// TODO [arkpar] Please document me
pub mod verification;
pub mod block_queue;
pub mod ethereum;
#[cfg(test)]
#[cfg(feature="json-tests")]
mod json_tests;

View File

@ -1,14 +1,14 @@
use util::*;
use basic_types::LogBloom;
/// A single log's entry.
/// A record of execution for a `LOG` operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LogEntry {
/// TODO [Gav Wood] Please document me
/// The address of the contract executing at the point of the `LOG` operation.
pub address: Address,
/// TODO [Gav Wood] Please document me
/// The topics associated with the `LOG` operation.
pub topics: Vec<H256>,
/// TODO [Gav Wood] Please document me
/// The data associated with the `LOG` operation.
pub data: Bytes,
}
@ -31,21 +31,6 @@ impl LogEntry {
}
}
/// Returns reference to address.
pub fn address(&self) -> &Address {
&self.address
}
/// Returns reference to topics.
pub fn topics(&self) -> &Vec<H256> {
&self.topics
}
/// Returns reference to data.
pub fn data(&self) -> &Bytes {
&self.data
}
/// Calculates the bloom of this log entry.
pub fn bloom(&self) -> LogBloom {
self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3()))

View File

@ -2,20 +2,22 @@ use util::*;
use account::*;
#[derive(Debug,Clone,PartialEq,Eq)]
/// Genesis account data. Does not have a DB overlay cache.
/// An account, expressed as Plain-Old-Data (hence the name).
/// Does not have a DB overlay cache, code hash or anything like that.
pub struct PodAccount {
/// TODO [Gav Wood] Please document me
/// The balance of the account.
pub balance: U256,
/// TODO [Gav Wood] Please document me
/// The nonce of the account.
pub nonce: U256,
/// TODO [Gav Wood] Please document me
/// The code of the account.
pub code: Bytes,
/// TODO [Gav Wood] Please document me
/// The storage of the account.
pub storage: BTreeMap<H256, H256>,
}
impl PodAccount {
/// Construct new object.
#[cfg(test)]
pub fn new(balance: U256, nonce: U256, code: Bytes, storage: BTreeMap<H256, H256>) -> PodAccount {
PodAccount { balance: balance, nonce: nonce, code: code, storage: storage }
}

View File

@ -2,7 +2,7 @@ use util::*;
use pod_account::*;
#[derive(Debug,Clone,PartialEq,Eq,Default)]
/// TODO [Gav Wood] Please document me
/// State of all accounts in the system expressed in Plain Old Data.
pub struct PodState (BTreeMap<Address, PodAccount>);
impl PodState {
@ -10,6 +10,7 @@ impl PodState {
pub fn new() -> PodState { Default::default() }
/// Contruct a new object from the `m`.
#[cfg(test)]
pub fn from(m: BTreeMap<Address, PodAccount>) -> PodState { PodState(m) }
/// Get the underlying map.
@ -21,6 +22,8 @@ impl PodState {
}
/// Drain object to get the underlying map.
#[cfg(test)]
#[cfg(feature = "json-tests")]
pub fn drain(self) -> BTreeMap<Address, PodAccount> { self.0 }
}

View File

@ -5,18 +5,18 @@ use log_entry::LogEntry;
/// Information describing execution of a transaction.
#[derive(Default, Debug, Clone)]
pub struct Receipt {
/// TODO [Gav Wood] Please document me
/// The state root after executing the transaction.
pub state_root: H256,
/// TODO [Gav Wood] Please document me
/// The total gas used in the block following execution of the transaction.
pub gas_used: U256,
/// TODO [Gav Wood] Please document me
/// The OR-wide combination of all logs' blooms for this transaction.
pub log_bloom: LogBloom,
/// TODO [Gav Wood] Please document me
/// The logs stemming from this transaction.
pub logs: Vec<LogEntry>,
}
impl Receipt {
/// TODO [Gav Wood] Please document me
/// Create a new receipt.
pub fn new(state_root: H256, gas_used: U256, logs: Vec<LogEntry>) -> Receipt {
Receipt {
state_root: state_root,

View File

@ -1,3 +1,5 @@
//! Creates and registers client and network services.
use util::*;
use spec::Spec;
use error::*;
@ -13,7 +15,7 @@ pub enum SyncMessage {
BlockVerified,
}
/// TODO [arkpar] Please document me
/// IO Message type used for Network service
pub type NetSyncMessage = NetworkIoMessage<SyncMessage>;
/// Client service setup. Creates and registers client and network services with the IO subsystem.

View File

@ -1,21 +1,10 @@
//! Parameters for a block chain.
use common::*;
use flate2::read::GzDecoder;
use engine::*;
use pod_state::*;
use null_engine::*;
/// Converts file from base64 gzipped bytes to json
pub fn gzip64res_to_json(source: &[u8]) -> Json {
// there is probably no need to store genesis in based64 gzip,
// but that's what go does, and it was easy to load it this way
let data = source.from_base64().expect("Genesis block is malformed!");
let data_ref: &[u8] = &data;
let mut decoder = GzDecoder::new(data_ref).expect("Gzip is invalid");
let mut s: String = "".to_owned();
decoder.read_to_string(&mut s).expect("Gzip is invalid");
Json::from_str(&s).expect("Json is invalid")
}
/// Convert JSON value to equivalent RLP representation.
// TODO: handle container types.
fn json_to_rlp(json: &Json) -> Bytes {
@ -45,53 +34,50 @@ fn json_to_rlp_map(json: &Json) -> HashMap<String, Bytes> {
/// chain and those to be interpreted by the active chain engine.
#[derive(Debug)]
pub struct Spec {
// User friendly spec name
/// TODO [Gav Wood] Please document me
/// User friendly spec name
pub name: String,
// What engine are we using for this?
/// TODO [Gav Wood] Please document me
/// What engine are we using for this?
pub engine_name: String,
/// Known nodes on the network in enode format.
pub nodes: Vec<String>,
// Parameters concerning operation of the specific engine we're using.
// Name -> RLP-encoded value
/// TODO [Gav Wood] Please document me
/// Parameters concerning operation of the specific engine we're using.
/// Maps the parameter name to an RLP-encoded value.
pub engine_params: HashMap<String, Bytes>,
// Builtin-contracts are here for now but would like to abstract into Engine API eventually.
/// TODO [Gav Wood] Please document me
/// Builtin-contracts we would like to see in the chain.
/// (In principle these are just hints for the engine since that has the last word on them.)
pub builtins: BTreeMap<Address, Builtin>,
// Genesis params.
/// TODO [Gav Wood] Please document me
/// The genesis block's parent hash field.
pub parent_hash: H256,
/// TODO [Gav Wood] Please document me
/// The genesis block's author field.
pub author: Address,
/// TODO [Gav Wood] Please document me
/// The genesis block's difficulty field.
pub difficulty: U256,
/// TODO [Gav Wood] Please document me
/// The genesis block's gas limit field.
pub gas_limit: U256,
/// TODO [Gav Wood] Please document me
/// The genesis block's gas used field.
pub gas_used: U256,
/// TODO [Gav Wood] Please document me
/// The genesis block's timestamp field.
pub timestamp: u64,
/// Transactions root of the genesis block. Should be SHA3_NULL_RLP.
pub transactions_root: H256,
/// Receipts root of the genesis block. Should be SHA3_NULL_RLP.
pub receipts_root: H256,
/// TODO [arkpar] Please document me
/// The genesis block's extra data field.
pub extra_data: Bytes,
/// TODO [Gav Wood] Please document me
genesis_state: PodState,
/// TODO [Gav Wood] Please document me
/// The number of seal fields in the genesis block.
pub seal_fields: usize,
/// TODO [Gav Wood] Please document me
/// Each seal field, expressed as RLP, concatenated.
pub seal_rlp: Bytes,
// May be prepopulated if we know this in advance.
state_root_memo: RwLock<Option<H256>>,
// Genesis state as plain old data.
genesis_state: PodState,
}
#[allow(wrong_self_convention)] // because to_engine(self) should be to_engine(&self)
@ -117,7 +103,7 @@ impl Spec {
/// Get the known knodes of the network in enode format.
pub fn nodes(&self) -> &Vec<String> { &self.nodes }
/// TODO [Gav Wood] Please document me
/// Get the header of the genesis block.
pub fn genesis_header(&self) -> Header {
Header {
parent_hash: self.parent_hash.clone(),

View File

@ -1,11 +1,15 @@
use common::*;
use engine::Engine;
use executive::Executive;
#[cfg(test)]
#[cfg(feature = "json-tests")]
use pod_account::*;
use pod_state::*;
#[cfg(test)]
#[cfg(feature = "json-tests")]
use pod_state::PodState;
//use state_diff::*; // TODO: uncomment once to_pod() works correctly.
/// TODO [Gav Wood] Please document me
/// Result type for the execution ("application") of a transaction.
pub type ApplyResult = Result<Receipt, Error>;
/// Representation of the entire state of all accounts in the system.
@ -20,6 +24,7 @@ pub struct State {
impl State {
/// Creates new state with empty state root
#[cfg(test)]
pub fn new(mut db: JournalDB, account_start_nonce: U256) -> State {
let mut root = H256::new();
{
@ -60,11 +65,6 @@ impl State {
&self.root
}
/// Expose the underlying database; good to use for calling `state.db().commit()`.
pub fn db(&mut self) -> &mut JournalDB {
&mut self.db
}
/// Create a new contract at address `contract`. If there is already an account at the address
/// it will have its code reset, ready for `init_code()`.
pub fn new_contract(&mut self, contract: &Address, balance: U256) {
@ -143,7 +143,6 @@ impl State {
// let old = self.to_pod();
let e = try!(Executive::new(self, env_info, engine).transact(t));
//println!("Executed: {:?}", e);
// TODO uncomment once to_pod() works correctly.
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
@ -153,16 +152,11 @@ impl State {
Ok(receipt)
}
/// TODO [debris] Please document me
/// Reverts uncommited changed.
pub fn revert(&mut self, backup: State) {
self.cache = backup.cache;
}
/// Convert into a JSON representation.
pub fn as_json(&self) -> String {
unimplemented!();
}
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
/// `accounts` is mutable because we may need to commit the code or storage and record that.
#[allow(match_ref_pats)]
@ -195,6 +189,8 @@ impl State {
Self::commit_into(&mut self.db, &mut self.root, self.cache.borrow_mut().deref_mut());
}
#[cfg(test)]
#[cfg(feature = "json-tests")]
/// Populate the state from `accounts`.
pub fn populate_from(&mut self, accounts: PodState) {
for (add, acc) in accounts.drain().into_iter() {
@ -202,17 +198,8 @@ impl State {
}
}
/// Populate a PodAccount map from this state.
pub fn to_hashmap_pod(&self) -> HashMap<Address, PodAccount> {
// TODO: handle database rather than just the cache.
self.cache.borrow().iter().fold(HashMap::new(), |mut m, (add, opt)| {
if let Some(ref acc) = *opt {
m.insert(add.clone(), PodAccount::from_account(acc));
}
m
})
}
#[cfg(test)]
#[cfg(feature = "json-tests")]
/// Populate a PodAccount map from this state.
pub fn to_pod(&self) -> PodState {
// TODO: handle database rather than just the cache.

View File

@ -1,12 +1,15 @@
use util::*;
#[cfg(test)]
use pod_state::*;
use account_diff::*;
#[derive(Debug,Clone,PartialEq,Eq)]
/// TODO [Gav Wood] Please document me
/// Expression for the delta between two system states. Encoded the
/// delta of every altered account.
pub struct StateDiff (BTreeMap<Address, AccountDiff>);
impl StateDiff {
#[cfg(test)]
/// Calculate and return diff between `pre` state and `post` state.
pub fn diff_pod(pre: &PodState, post: &PodState) -> StateDiff {
StateDiff(pre.get().keys().merge(post.get().keys()).filter_map(|acc| AccountDiff::diff_pod(pre.get().get(acc), post.get().get(acc)).map(|d|(acc.clone(), d))).collect())

View File

@ -1,3 +1,4 @@
//! Execution environment substate.
use common::*;
/// State changes which should be applied in finalize,
@ -25,7 +26,7 @@ impl Substate {
}
}
/// TODO [Gav Wood] Please document me
/// Merge secondary substate `s` into self, accruing each element correspondingly.
pub fn accrue(&mut self, s: Substate) {
self.suicides.extend(s.suicides.into_iter());
self.logs.extend(s.logs.into_iter());

View File

@ -1,6 +1,7 @@
#[cfg(feature = "json-tests")]
use client::{BlockChainClient, Client};
use std::env;
use super::test_common::*;
use common::*;
use std::path::PathBuf;
use spec::*;
use std::fs::{remove_dir_all};
@ -8,6 +9,8 @@ use blockchain::{BlockChain};
use state::*;
use rocksdb::*;
#[cfg(feature = "json-tests")]
pub enum ChainEra {
Frontier,
Homestead,
@ -43,10 +46,10 @@ impl Drop for RandomTempPath {
}
}
#[allow(dead_code)]
#[cfg(test)]
pub struct GuardedTempResult<T> {
result: T,
temp: RandomTempPath
_temp: RandomTempPath
}
impl<T> GuardedTempResult<T> {
@ -111,6 +114,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&Transaction
rlp.out()
}
#[cfg(feature = "json-tests")]
pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
@ -145,11 +149,12 @@ pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>
client.import_verified_blocks(&IoChannel::disconnected());
GuardedTempResult::<Arc<Client>> {
temp: dir,
_temp: dir,
result: client
}
}
#[cfg(feature = "json-tests")]
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
@ -162,7 +167,7 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<
client.import_verified_blocks(&IoChannel::disconnected());
GuardedTempResult::<Arc<Client>> {
temp: dir,
_temp: dir,
result: client
}
}
@ -175,7 +180,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockCh
}
GuardedTempResult::<BlockChain> {
temp: temp,
_temp: temp,
result: bc
}
}
@ -188,7 +193,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes
}
GuardedTempResult::<BlockChain> {
temp: temp,
_temp: temp,
result: bc
}
}
@ -198,7 +203,7 @@ pub fn generate_dummy_empty_blockchain() -> GuardedTempResult<BlockChain> {
let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path());
GuardedTempResult::<BlockChain> {
temp: temp,
_temp: temp,
result: bc
}
}
@ -208,7 +213,7 @@ pub fn get_temp_journal_db() -> GuardedTempResult<JournalDB> {
let db = DB::open_default(temp.as_str()).unwrap();
let journal_db = JournalDB::new(db);
GuardedTempResult {
temp: temp,
_temp: temp,
result: journal_db
}
}
@ -217,7 +222,7 @@ pub fn get_temp_state() -> GuardedTempResult<State> {
let temp = RandomTempPath::new();
let journal_db = get_temp_journal_db_in(temp.as_path());
GuardedTempResult {
temp: temp,
_temp: temp,
result: State::new(journal_db, U256::from(0u8))
}
}
@ -246,6 +251,7 @@ pub fn get_good_dummy_block() -> Bytes {
create_test_block(&block_header)
}
#[cfg(feature = "json-tests")]
pub fn get_bad_state_dummy_block() -> Bytes {
let mut block_header = Header::new();
let test_spec = get_test_spec();

View File

@ -1,11 +1 @@
#[macro_use]
mod test_common;
mod transaction;
mod executive;
mod state;
mod client;
mod chain;
pub mod helpers;
mod homestead_state;
mod homestead_chain;

View File

@ -1,14 +1,16 @@
//! Transaction data structure.
use util::*;
use basic_types::*;
use error::*;
use evm::Schedule;
#[derive(Debug, Clone)]
/// TODO [Gav Wood] Please document me
/// Transaction action type.
pub enum Action {
/// TODO [Gav Wood] Please document me
/// Create creates new contract.
Create,
/// TODO [debris] Please document me
/// Calls contract at given address.
Call(Address),
}
@ -20,25 +22,25 @@ impl Default for Action {
/// or contract creation operation.
#[derive(Default, Debug, Clone)]
pub struct Transaction {
/// TODO [debris] Please document me
/// Nonce.
pub nonce: U256,
/// TODO [debris] Please document me
/// Gas price.
pub gas_price: U256,
/// TODO [debris] Please document me
/// Gas paid up front for transaction execution.
pub gas: U256,
/// TODO [debris] Please document me
/// Action, can be either call or contract create.
pub action: Action,
/// TODO [debris] Please document me
/// Transfered value.
pub value: U256,
/// TODO [Gav Wood] Please document me
/// Transaction data.
pub data: Bytes,
// signature
/// TODO [Gav Wood] Please document me
/// The V field of the signature, either 27 or 28; helps describe the point on the curve.
pub v: u8,
/// TODO [Gav Wood] Please document me
/// The R field of the signature; helps describe the point on the curve.
pub r: U256,
/// TODO [debris] Please document me
/// The S field of the signature; helps describe the point on the curve.
pub s: U256,
hash: RefCell<Option<H256>>,
@ -46,7 +48,9 @@ pub struct Transaction {
}
impl Transaction {
/// TODO [Gav Wood] Please document me
/// Create a new transaction.
#[cfg(test)]
#[cfg(feature = "json-tests")]
pub fn new() -> Self {
Transaction {
nonce: x!(0),
@ -62,24 +66,9 @@ impl Transaction {
sender: RefCell::new(None),
}
}
/// Create a new message-call transaction.
pub fn new_call(to: Address, value: U256, data: Bytes, gas: U256, gas_price: U256, nonce: U256) -> Transaction {
Transaction {
nonce: nonce,
gas_price: gas_price,
gas: gas,
action: Action::Call(to),
value: value,
data: data,
v: 0,
r: x!(0),
s: x!(0),
hash: RefCell::new(None),
sender: RefCell::new(None),
}
}
/// Create a new contract-creation transaction.
#[cfg(test)]
pub fn new_create(value: U256, data: Bytes, gas: U256, gas_price: U256, nonce: U256) -> Transaction {
Transaction {
nonce: nonce,
@ -96,19 +85,6 @@ impl Transaction {
}
}
/// Get the nonce of the transaction.
pub fn nonce(&self) -> &U256 { &self.nonce }
/// Get the gas price of the transaction.
pub fn gas_price(&self) -> &U256 { &self.gas_price }
/// Get the gas of the transaction.
pub fn gas(&self) -> &U256 { &self.gas }
/// Get the action of the transaction (Create or Call).
pub fn action(&self) -> &Action { &self.action }
/// Get the value of the transaction.
pub fn value(&self) -> &U256 { &self.value }
/// Get the data of the transaction.
pub fn data(&self) -> &Bytes { &self.data }
/// Append object into RLP stream, optionally with or without the signature.
pub fn rlp_append_opt(&self, s: &mut RlpStream, with_seal: Seal) {
s.begin_list(6 + match with_seal { Seal::With => 3, _ => 0 });
@ -179,11 +155,6 @@ impl Transaction {
}
}
/// Note that some fields have changed. Resets the memoised hash.
pub fn note_dirty(&self) {
*self.hash.borrow_mut() = None;
}
/// 0 is `v` is 27, 1 if 28, and 4 otherwise.
pub fn standard_v(&self) -> u8 { match self.v { 27 => 0, 28 => 1, _ => 4 } }
@ -216,6 +187,7 @@ impl Transaction {
}
/// Signs the transaction as coming from `sender`.
#[cfg(test)]
pub fn signed(self, secret: &Secret) -> Transaction { let mut r = self; r.sign(secret); r }
/// Get the transaction cost in gas for the given params.
@ -241,6 +213,9 @@ impl Transaction {
}
/// Do basic validation, checking for valid signature and minimum gas,
// TODO: consider use in block validation.
#[cfg(test)]
#[cfg(feature = "json-tests")]
pub fn validate(self, schedule: &Schedule, require_low: bool) -> Result<Transaction, Error> {
if require_low && !ec::is_low_s(&self.s) {
return Err(Error::Util(UtilError::Crypto(CryptoError::InvalidSignature)));

View File

@ -154,7 +154,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root.clone(), found: got.state_root.clone() })))
}
if expected.receipts_root != got.receipts_root {
return Err(From::from(BlockError::InvalidReceiptsStateRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() })))
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() })))
}
Ok(())
}

View File

@ -1,3 +1,3 @@
#!/bin/sh
echo "#!/bin/sh\ncargo test" >> ./.git/hooks/pre-push
echo "#!/bin/sh\ncargo test -p ethcore" >> ./.git/hooks/pre-push
chmod +x ./.git/hooks/pre-push

466
install-deps.sh Executable file
View File

@ -0,0 +1,466 @@
#!/usr/bin/env bash
function run_installer()
{
####### Init vars
HOMEBREW_PREFIX=/usr/local
HOMEBREW_CACHE=/Library/Caches/Homebrew
HOMEBREW_REPO=https://github.com/Homebrew/homebrew
OSX_REQUIERED_VERSION="10.7.0"
declare OS_TYPE
declare OSX_VERSION
declare GIT_PATH
declare RUBY_PATH
declare BREW_PATH
declare INSTALL_FILES=""
errorMessages=""
isOsVersion=false
isGit=false
isRuby=false
isBrew=false
canContinue=true
depCount=0
depFound=0
####### Setup colors
red=`tput setaf 1`
green=`tput setaf 2`
yellow=`tput setaf 3`
blue=`tput setaf 4`
magenta=`tput setaf 5`
cyan=`tput setaf 6`
white=`tput setaf 7`
b=`tput bold`
u=`tput sgr 0 1`
ul=`tput smul`
xl=`tput rmul`
stou=`tput smso`
xtou=`tput rmso`
dim=`tput dim`
reverse=`tput rev`
reset=`tput sgr0`
function head() {
echo "${blue}${b}==>${white} $1${reset}"
}
function info() {
echo "${blue}${b}==>${reset} $1"
}
function successHeading() {
echo "${green}${b}==> $1${reset}"
}
function success() {
echo "${green}${b}==>${reset}${green} $1${reset}"
}
function error() {
echo "${red}==> ${u}${b}${red}$1${reset}"
}
function smallError() {
echo "${red}==>${reset} $1"
}
function green() {
echo "${green}$1${reset}"
}
function red() {
echo "${red}$1${reset}"
}
function check() {
echo "${green}${bold}${reset} $1${reset}"
}
function uncheck() {
echo "${red}${bold}${reset} $1${reset}"
}
####### Setup methods
function wait_for_user() {
while :
do
read -p "${blue}==>${reset} $1 [Y/n] " imp
case $imp in
[yY] ) echo; break ;;
'' ) echo; break ;;
[nN] ) abortInstall "${red}==>${reset} Process stopped by user. To resume the install run the one-liner command again." ;;
* ) echo "Unrecognized option provided. Please provide either 'Y' or 'N'";
esac
done
}
function exe() {
echo "\$ $@"; "$@"
}
function detectOS() {
if [[ "$OSTYPE" == "linux-gnu" ]]
then
OS_TYPE="linux"
get_linux_dependencies
elif [[ "$OSTYPE" == "darwin"* ]]
then
OS_TYPE="osx"
get_osx_dependencies
else
OS_TYPE="win"
abortInstall "${red}==>${reset} ${b}OS not supported:${reset} parity one-liner currently support OS X and Linux.\nFor instructions on installing parity on other platforms please visit ${u}${blue}http://ethcore.io/${reset}"
fi
echo
if [[ $depCount == $depFound ]]
then
green "Found all dependencies ($depFound/$depCount)"
else
if [[ $canContinue == true ]]
then
red "Some dependencies are missing ($depFound/$depCount)"
elif [[ $canContinue == false && $depFound == 0 ]]
then
red "All dependencies are missing and cannot be auto-installed ($depFound/$depCount)"
abortInstall "$errorMessages";
elif [[ $canContinue == false ]]
then
red "Some dependencies which cannot be auto-installed are missing ($depFound/$depCount)"
abortInstall "$errorMessages";
fi
fi
}
function get_osx_dependencies()
{
macos_version
find_git
find_ruby
find_brew
}
function macos_version()
{
declare -a reqVersion
declare -a localVersion
depCount=$((depCount+1))
OSX_VERSION=`/usr/bin/sw_vers -productVersion 2>/dev/null`
if [ -z "$OSX_VERSION" ]
then
uncheck "OS X version not supported 🔥"
isOsVersion=false
canContinue=false
else
IFS='.' read -a localVersion <<< "$OSX_VERSION"
IFS='.' read -a reqVersion <<< "$OSX_REQUIERED_VERSION"
if (( ${reqVersion[0]} <= ${localVersion[0]} )) && (( ${reqVersion[1]} <= ${localVersion[1]} ))
then
check "OS X Version ${OSX_VERSION}"
isOsVersion=true
depFound=$((depFound+1))
return
else
uncheck "OS X version not supported"
isOsVersion=false
canContinue=false
fi
fi
errorMessages+="${red}==>${reset} ${b}Mac OS version too old:${reset} eth requires OS X version ${red}$OSX_REQUIERED_VERSION${reset} at least in order to run.\n"
errorMessages+=" Please update the OS and reload the install process.\n"
}
function find_eth()
{
ETH_PATH=`which eth 2>/dev/null`
if [[ -f $ETH_PATH ]]
then
check "Found eth: $ETH_PATH"
echo "$($ETH_PATH -V)"
isEth=true
else
uncheck "Eth is missing"
isEth=false
fi
}
function find_git()
{
depCount=$((depCount+1))
GIT_PATH=`which git 2>/dev/null`
if [[ -f $GIT_PATH ]]
then
check "$($GIT_PATH --version)"
isGit=true
depFound=$((depFound+1))
else
uncheck "Git is missing"
isGit=false
fi
}
function find_ruby()
{
depCount=$((depCount+1))
RUBY_PATH=`which ruby 2>/dev/null`
if [[ -f $RUBY_PATH ]]
then
RUBY_VERSION=`ruby -e "print RUBY_VERSION"`
check "Ruby ${RUBY_VERSION}"
isRuby=true
depFound=$((depFound+1))
else
uncheck "Ruby is missing 🔥"
isRuby=false
canContinue=false
errorMessages+="${red}==>${reset} ${b}Couldn't find Ruby:${reset} Brew requires Ruby which could not be found.\n"
errorMessages+=" Please install Ruby using these instructions ${u}${blue}https://www.ruby-lang.org/en/documentation/installation/${reset}.\n"
fi
}
function find_brew()
{
BREW_PATH=`which brew 2>/dev/null`
if [[ -f $BREW_PATH ]]
then
check "$($BREW_PATH -v)"
isBrew=true
depFound=$((depFound+1))
else
uncheck "Homebrew is missing"
isBrew=false
INSTALL_FILES+="${blue}${dim}==> Homebrew:${reset}\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/bin/brew\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/Library\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/share/man/man1/brew.1\n"
fi
depCount=$((depCount+1))
}
function install_brew()
{
if [[ $isBrew == false ]]
then
head "Installing Homebrew"
if [[ $isRuby == true ]]
then
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
else
cd /usr
if [[ ! -d $HOMEBREW_PREFIX ]]
then
sudo mkdir $HOMEBREW_PREFIX
sudo chmod g+rwx $HOMEBREW_PREFIX
fi
if [[ ! -d $HOMEBREW_CACHE ]]
then
sudo mkdir $HOMEBREW_CACHE
sudo chmod g+rwx $HOMEBREW_CACHE
fi
DEVELOPER_DIR=`/usr/bin/xcode-select -print-path 2>/dev/null`
if [[ ! $(ls -A $DEVELOPER_DIR) || ! -f $DEVELOPER_DIR/usr/bin/git ]]
then
info "Installing the Command Line Tools (expect a GUI popup):"
sudo /usr/bin/xcode-select --install
echo "Press any key when the installation has completed"
fi
cd $HOMEBREW_PREFIX
bash -o pipefail -c "curl -fsSL ${HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1"
fi
find_brew
echo
if [[ $isBrew == false ]]
then
abortInstall "Couldn't install brew"
fi
fi
}
function osx_installer()
{
osx_dependency_installer
info "Updating brew"
exe brew update
echo
info "Installing rocksdb"
exe brew install rocksdb
info "Installing multirust"
exe brew install multirust
sudo multirust update nightly
sudo multirust default nightly
echo
}
function osx_dependency_installer()
{
if [[ $isGit == false ]];
then
echo "Installing Git"
fi
if [[ $isRuby == false ]];
then
echo "Installing Ruby"
fi
if [[ $isBrew == false ]];
then
install_brew
fi
}
function get_linux_dependencies()
{
find_apt
}
function find_apt()
{
APT_PATH=`which apt-get 2>/dev/null`
if [[ -f $APT_PATH ]]
then
check "apt-get"
echo "$($APT_PATH -v)"
isApt=true
else
uncheck "apt-get is missing"
isApt=false
fi
}
function linux_rocksdb_installer()
{
oldpwd=`pwd`
cd /tmp
exe git clone --branch v4.1 --depth=1 https://github.com/facebook/rocksdb.git
cd rocksdb
exe make shared_lib
sudo cp -a librocksdb.so* /usr/lib
sudo ldconfig
cd /tmp
rm -rf /tmp/rocksdb
cd $oldpwd
}
function linux_installer()
{
info "Installing git"
sudo apt-get install -q -y git
echo
info "Installing rocksdb"
linux_rocksdb_installer
echo
info "Installing multirust"
curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes
sudo multirust update nightly
sudo multirust default nightly
echo
}
function install()
{
echo
head "Installing Parity build dependencies"
if [[ $OS_TYPE == "osx" ]]
then
osx_installer
elif [[ $OS_TYPE == "linux" ]]
then
linux_installer
fi
}
function verify_installation()
{
info "Verifying installation"
# find_eth
# if [[ $isEth == false ]]
# then
# abortInstall
# fi
}
function abortInstall()
{
echo
error "Installation failed"
echo -e "$1"
echo
exit 0
}
function finish()
{
# echo
# successHeading "Installation successful!"
# head "Next steps"
# info "Run ${cyan}\`\`${reset} to get started.${reset}"
# echo
exit 0
}
# Check dependencies
head "Checking OS dependencies"
detectOS
echo
head "In addition to the parity build dependencies, this script will install:"
echo "$INSTALL_FILES"
echo
# Prompt user to continue or abort
wait_for_user "${b}OK,${reset} let's go!"
# Install dependencies and eth
install
# Check installation
verify_installation
# Display goodby message
finish
}
run_installer

475
install-parity.sh Executable file
View File

@ -0,0 +1,475 @@
#!/usr/bin/env bash
function run_installer()
{
####### Init vars
HOMEBREW_PREFIX=/usr/local
HOMEBREW_CACHE=/Library/Caches/Homebrew
HOMEBREW_REPO=https://github.com/Homebrew/homebrew
OSX_REQUIERED_VERSION="10.7.0"
declare OS_TYPE
declare OSX_VERSION
declare GIT_PATH
declare RUBY_PATH
declare BREW_PATH
declare INSTALL_FILES=""
errorMessages=""
isOsVersion=false
isGit=false
isRuby=false
isBrew=false
canContinue=true
depCount=0
depFound=0
####### Setup colors
red=`tput setaf 1`
green=`tput setaf 2`
yellow=`tput setaf 3`
blue=`tput setaf 4`
magenta=`tput setaf 5`
cyan=`tput setaf 6`
white=`tput setaf 7`
b=`tput bold`
u=`tput sgr 0 1`
ul=`tput smul`
xl=`tput rmul`
stou=`tput smso`
xtou=`tput rmso`
dim=`tput dim`
reverse=`tput rev`
reset=`tput sgr0`
function head() {
echo "${blue}${b}==>${white} $1${reset}"
}
function info() {
echo "${blue}${b}==>${reset} $1"
}
function successHeading() {
echo "${green}${b}==> $1${reset}"
}
function success() {
echo "${green}${b}==>${reset}${green} $1${reset}"
}
function error() {
echo "${red}==> ${u}${b}${red}$1${reset}"
}
function smallError() {
echo "${red}==>${reset} $1"
}
function green() {
echo "${green}$1${reset}"
}
function red() {
echo "${red}$1${reset}"
}
function check() {
echo "${green}${bold}${reset} $1${reset}"
}
function uncheck() {
echo "${red}${bold}${reset} $1${reset}"
}
####### Setup methods
function wait_for_user() {
while :
do
read -p "${blue}==>${reset} $1 [Y/n] " imp
case $imp in
[yY] ) echo; break ;;
'' ) echo; break ;;
[nN] ) abortInstall "${red}==>${reset} Process stopped by user. To resume the install run the one-liner command again." ;;
* ) echo "Unrecognized option provided. Please provide either 'Y' or 'N'";
esac
done
}
function exe() {
echo "\$ $@"; "$@"
}
function detectOS() {
if [[ "$OSTYPE" == "linux-gnu" ]]
then
OS_TYPE="linux"
get_linux_dependencies
elif [[ "$OSTYPE" == "darwin"* ]]
then
OS_TYPE="osx"
get_osx_dependencies
else
OS_TYPE="win"
abortInstall "${red}==>${reset} ${b}OS not supported:${reset} parity one-liner currently support OS X and Linux.\nFor instructions on installing parity on other platforms please visit ${u}${blue}http://ethcore.io/${reset}"
fi
echo
if [[ $depCount == $depFound ]]
then
green "Found all dependencies ($depFound/$depCount)"
else
if [[ $canContinue == true ]]
then
red "Some dependencies are missing ($depFound/$depCount)"
elif [[ $canContinue == false && $depFound == 0 ]]
then
red "All dependencies are missing and cannot be auto-installed ($depFound/$depCount)"
abortInstall "$errorMessages";
elif [[ $canContinue == false ]]
then
red "Some dependencies which cannot be auto-installed are missing ($depFound/$depCount)"
abortInstall "$errorMessages";
fi
fi
}
function get_osx_dependencies()
{
macos_version
find_git
find_ruby
find_brew
}
function macos_version()
{
declare -a reqVersion
declare -a localVersion
depCount=$((depCount+1))
OSX_VERSION=`/usr/bin/sw_vers -productVersion 2>/dev/null`
if [ -z "$OSX_VERSION" ]
then
uncheck "OS X version not supported 🔥"
isOsVersion=false
canContinue=false
else
IFS='.' read -a localVersion <<< "$OSX_VERSION"
IFS='.' read -a reqVersion <<< "$OSX_REQUIERED_VERSION"
if (( ${reqVersion[0]} <= ${localVersion[0]} )) && (( ${reqVersion[1]} <= ${localVersion[1]} ))
then
check "OS X Version ${OSX_VERSION}"
isOsVersion=true
depFound=$((depFound+1))
return
else
uncheck "OS X version not supported"
isOsVersion=false
canContinue=false
fi
fi
errorMessages+="${red}==>${reset} ${b}Mac OS version too old:${reset} eth requires OS X version ${red}$OSX_REQUIERED_VERSION${reset} at least in order to run.\n"
errorMessages+=" Please update the OS and reload the install process.\n"
}
function find_eth()
{
ETH_PATH=`which parity 2>/dev/null`
if [[ -f $ETH_PATH ]]
then
check "Found parity: $ETH_PATH"
echo "$($ETH_PATH -V)"
isEth=true
else
uncheck "parity is missing"
isEth=false
fi
}
function find_git()
{
depCount=$((depCount+1))
GIT_PATH=`which git 2>/dev/null`
if [[ -f $GIT_PATH ]]
then
check "$($GIT_PATH --version)"
isGit=true
depFound=$((depFound+1))
else
uncheck "Git is missing"
isGit=false
fi
}
function find_ruby()
{
depCount=$((depCount+1))
RUBY_PATH=`which ruby 2>/dev/null`
if [[ -f $RUBY_PATH ]]
then
RUBY_VERSION=`ruby -e "print RUBY_VERSION"`
check "Ruby ${RUBY_VERSION}"
isRuby=true
depFound=$((depFound+1))
else
uncheck "Ruby is missing 🔥"
isRuby=false
canContinue=false
errorMessages+="${red}==>${reset} ${b}Couldn't find Ruby:${reset} Brew requires Ruby which could not be found.\n"
errorMessages+=" Please install Ruby using these instructions ${u}${blue}https://www.ruby-lang.org/en/documentation/installation/${reset}.\n"
fi
}
function find_brew()
{
BREW_PATH=`which brew 2>/dev/null`
if [[ -f $BREW_PATH ]]
then
check "$($BREW_PATH -v)"
isBrew=true
depFound=$((depFound+1))
else
uncheck "Homebrew is missing"
isBrew=false
INSTALL_FILES+="${blue}${dim}==> Homebrew:${reset}\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/bin/brew\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/Library\n"
INSTALL_FILES+=" ${blue}${dim}${reset} $HOMEBREW_PREFIX/share/man/man1/brew.1\n"
fi
depCount=$((depCount+1))
}
function install_brew()
{
if [[ $isBrew == false ]]
then
head "Installing Homebrew"
if [[ $isRuby == true ]]
then
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
else
cd /usr
if [[ ! -d $HOMEBREW_PREFIX ]]
then
sudo mkdir $HOMEBREW_PREFIX
sudo chmod g+rwx $HOMEBREW_PREFIX
fi
if [[ ! -d $HOMEBREW_CACHE ]]
then
sudo mkdir $HOMEBREW_CACHE
sudo chmod g+rwx $HOMEBREW_CACHE
fi
DEVELOPER_DIR=`/usr/bin/xcode-select -print-path 2>/dev/null`
if [[ ! $(ls -A $DEVELOPER_DIR) || ! -f $DEVELOPER_DIR/usr/bin/git ]]
then
info "Installing the Command Line Tools (expect a GUI popup):"
sudo /usr/bin/xcode-select --install
echo "Press any key when the installation has completed"
fi
cd $HOMEBREW_PREFIX
bash -o pipefail -c "curl -fsSL ${HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1"
fi
find_brew
echo
if [[ $isBrew == false ]]
then
abortInstall "Couldn't install brew"
fi
fi
}
function osx_installer()
{
osx_dependency_installer
info "Adding ethcore repository"
exe brew tap ethcore/ethcore git@github.com:ethcore/homebrew-ethcore.git
echo
info "Updating brew"
exe brew update
echo
info "Installing parity"
if [[ $isEth == true ]]
then
exe brew reinstall parity
else
exe brew install parity
exe brew linkapps parity
fi
echo
}
function osx_dependency_installer()
{
if [[ $isGit == false ]];
then
echo "Installing Git"
fi
if [[ $isRuby == false ]];
then
echo "Installing Ruby"
fi
if [[ $isBrew == false ]];
then
install_brew
fi
}
function get_linux_dependencies()
{
find_apt
}
function find_apt()
{
APT_PATH=`which apt-get 2>/dev/null`
if [[ -f $APT_PATH ]]
then
check "apt-get"
echo "$($APT_PATH -v)"
isApt=true
else
uncheck "apt-get is missing"
isApt=false
fi
}
function linux_rocksdb_installer()
{
oldpwd=`pwd`
cd /tmp
exe git clone --branch v4.1 --depth=1 https://github.com/facebook/rocksdb.git
cd rocksdb
exe make shared_lib
sudo cp -a librocksdb.so* /usr/lib
sudo ldconfig
cd /tmp
rm -rf /tmp/rocksdb
cd $oldpwd
}
function linux_installer()
{
info "Installing git"
sudo apt-get install -q -y git
echo
info "Installing rocksdb"
linux_rocksdb_installer
echo
info "Installing multirust"
curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes
sudo multirust update nightly
sudo multirust default nightly
echo
info "Installing parity"
wget --quiet --output-document=- http://ethcore.io/download/parity.deb | dpkg --install -
}
function install()
{
echo
head "Installing Parity build dependencies"
if [[ $OS_TYPE == "osx" ]]
then
osx_installer
elif [[ $OS_TYPE == "linux" ]]
then
linux_installer
fi
}
function verify_installation()
{
info "Verifying installation"
find_eth
if [[ $isEth == false ]]
then
abortInstall
fi
}
function abortInstall()
{
echo
error "Installation failed"
echo -e "$1"
echo
exit 0
}
function finish()
{
# echo
# successHeading "Installation successful!"
# head "Next steps"
# info "Run ${cyan}\`\`${reset} to get started.${reset}"
# echo
exit 0
}
# Check dependencies
head "Checking OS dependencies"
detectOS
echo
head "In addition to the parity build dependencies, this script will install:"
echo "$INSTALL_FILES"
echo
# Prompt user to continue or abort
wait_for_user "${b}OK,${reset} let's go!"
# Install dependencies and eth
install
# Check installation
verify_installation
# Display goodby message
finish
}
run_installer

View File

@ -13,4 +13,5 @@ ethcore = { path = ".." }
clippy = "0.0.37"
log = "0.3"
env_logger = "0.3"
time = "0.1.34"

View File

@ -22,6 +22,7 @@ use range_collection::{RangeCollection, ToUsize, FromUsize};
use ethcore::error::*;
use ethcore::block::Block;
use io::SyncIo;
use time;
impl ToUsize for BlockNumber {
fn to_usize(&self) -> usize {
@ -61,6 +62,8 @@ const RECEIPTS_PACKET: u8 = 0x10;
const NETWORK_ID: U256 = ONE_U256; //TODO: get this from parent
const CONNECTION_TIMEOUT_SEC: f64 = 30f64;
struct Header {
/// Header data
data: Bytes,
@ -138,6 +141,8 @@ struct PeerInfo {
asking: PeerAsking,
/// A set of block numbers being requested
asking_blocks: Vec<BlockNumber>,
/// Request timestamp
ask_time: f64,
}
/// Blockchain sync handler.
@ -250,6 +255,7 @@ impl ChainSync {
genesis: try!(r.val_at(4)),
asking: PeerAsking::Nothing,
asking_blocks: Vec::new(),
ask_time: 0f64,
};
trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest, peer.genesis);
@ -408,6 +414,7 @@ impl ChainSync {
trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h);
let header_view = HeaderView::new(header_rlp.as_raw());
// TODO: Decompose block and add to self.headers and self.bodies instead
let mut unknown = false;
if header_view.number() == From::from(self.last_imported_block + 1) {
match io.chain().import_block(block_rlp.as_raw().to_vec()) {
Err(ImportError::AlreadyInChain) => {
@ -416,6 +423,10 @@ impl ChainSync {
Err(ImportError::AlreadyQueued) => {
trace!(target: "sync", "New block already queued {:?}", h);
},
Err(ImportError::UnknownParent) => {
unknown = true;
trace!(target: "sync", "New block with unknown parent {:?}", h);
},
Ok(_) => {
trace!(target: "sync", "New block queued {:?}", h);
},
@ -426,6 +437,9 @@ impl ChainSync {
};
}
else {
unknown = true;
}
if unknown {
trace!(target: "sync", "New block unknown {:?}", h);
//TODO: handle too many unknown blocks
let difficulty: U256 = try!(r.val_at(1));
@ -795,6 +809,7 @@ impl ChainSync {
Ok(_) => {
let mut peer = self.peers.get_mut(&peer_id).unwrap();
peer.asking = asking;
peer.ask_time = time::precise_time_s();
}
}
}
@ -969,6 +984,16 @@ impl ChainSync {
})
}
/// Handle peer timeouts
pub fn maintain_peers(&self, io: &mut SyncIo) {
let tick = time::precise_time_s();
for (peer_id, peer) in &self.peers {
if peer.asking != PeerAsking::Nothing && (tick - peer.ask_time) > CONNECTION_TIMEOUT_SEC {
io.disconnect_peer(*peer_id);
}
}
}
/// Maintain other peers. Send out any new blocks and transactions
pub fn _maintain_sync(&mut self, _io: &mut SyncIo) {
}

View File

@ -9,6 +9,8 @@ use ethcore::service::SyncMessage;
pub trait SyncIo {
/// Disable a peer
fn disable_peer(&mut self, peer_id: PeerId);
/// Disconnect peer
fn disconnect_peer(&mut self, peer_id: PeerId);
/// Respond to current request with a packet. Can be called from an IO handler for incoming packet.
fn respond(&mut self, packet_id: PacketId, data: Vec<u8>) -> Result<(), UtilError>;
/// Send a packet to a peer.
@ -42,6 +44,10 @@ impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> {
self.network.disable_peer(peer_id);
}
fn disconnect_peer(&mut self, peer_id: PeerId) {
self.network.disconnect_peer(peer_id);
}
fn respond(&mut self, packet_id: PacketId, data: Vec<u8>) -> Result<(), UtilError>{
self.network.respond(packet_id, data)
}

View File

@ -33,11 +33,13 @@ extern crate log;
extern crate ethcore_util as util;
extern crate ethcore;
extern crate env_logger;
extern crate time;
use std::ops::*;
use std::sync::*;
use ethcore::client::Client;
use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, PeerId};
use util::io::TimerToken;
use chain::ChainSync;
use ethcore::service::SyncMessage;
use io::NetSyncIo;
@ -87,7 +89,8 @@ impl EthSync {
}
impl NetworkProtocolHandler<SyncMessage> for EthSync {
fn initialize(&self, _io: &NetworkContext<SyncMessage>) {
fn initialize(&self, io: &NetworkContext<SyncMessage>) {
io.register_timer(0, 1000).expect("Error registering sync timer");
}
fn read(&self, io: &NetworkContext<SyncMessage>, peer: &PeerId, packet_id: u8, data: &[u8]) {
@ -101,6 +104,10 @@ impl NetworkProtocolHandler<SyncMessage> for EthSync {
fn disconnected(&self, io: &NetworkContext<SyncMessage>, peer: &PeerId) {
self.sync.write().unwrap().on_peer_aborting(&mut NetSyncIo::new(io, self.chain.deref()), *peer);
}
fn timeout(&self, io: &NetworkContext<SyncMessage>, _timer: TimerToken) {
self.sync.write().unwrap().maintain_peers(&mut NetSyncIo::new(io, self.chain.deref()));
}
}

View File

@ -1,104 +0,0 @@
use util::*;
use sync::*;
use spec::Spec;
use error::*;
use std::env;
use client::Client;
/// Message type for external and internal events
#[derive(Clone)]
pub enum SyncMessage {
/// New block has been imported into the blockchain
NewChainBlock(Bytes), //TODO: use Cow
/// A block is ready
BlockVerified,
}
/// TODO [arkpar] Please document me
pub type NetSyncMessage = NetworkIoMessage<SyncMessage>;
/// Client service setup. Creates and registers client and network services with the IO subsystem.
pub struct ClientService {
net_service: NetworkService<SyncMessage>,
client: Arc<Client>,
sync: Arc<EthSync>,
}
impl ClientService {
/// Start the service in a separate thread.
pub fn start(spec: Spec, net_config: NetworkConfiguration) -> Result<ClientService, Error> {
let mut net_service = try!(NetworkService::start(net_config));
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");
dir.push(H64::from(spec.genesis_header().hash()).hex());
let client = try!(Client::new(spec, &dir, net_service.io().channel()));
let sync = EthSync::register(&mut net_service, client.clone());
let client_io = Arc::new(ClientIoHandler {
client: client.clone()
});
try!(net_service.io().register_handler(client_io));
Ok(ClientService {
net_service: net_service,
client: client,
sync: sync,
})
}
/// Get the network service.
pub fn add_node(&mut self, _enode: &str) {
unimplemented!();
}
/// TODO [arkpar] Please document me
pub fn io(&mut self) -> &mut IoService<NetSyncMessage> {
self.net_service.io()
}
/// TODO [arkpar] Please document me
pub fn client(&self) -> Arc<Client> {
self.client.clone()
}
/// Get shared sync handler
pub fn sync(&self) -> Arc<EthSync> {
self.sync.clone()
}
}
/// IO interface for the Client handler
struct ClientIoHandler {
client: Arc<Client>
}
const CLIENT_TICK_TIMER: TimerToken = 0;
const CLIENT_TICK_MS: u64 = 5000;
impl IoHandler<NetSyncMessage> for ClientIoHandler {
fn initialize(&self, io: &IoContext<NetSyncMessage>) {
io.register_timer(CLIENT_TICK_TIMER, CLIENT_TICK_MS).expect("Error registering client timer");
}
fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) {
if timer == CLIENT_TICK_TIMER {
self.client.tick();
}
}
#[allow(match_ref_pats)]
#[allow(single_match)]
fn message(&self, io: &IoContext<NetSyncMessage>, net_message: &NetSyncMessage) {
if let &UserMessage(ref message) = net_message {
match message {
&SyncMessage::BlockVerified => {
self.client.import_verified_blocks(&io.channel());
},
_ => {}, // ignore other messages
}
}
}
}

View File

@ -209,6 +209,9 @@ impl<'p> SyncIo for TestIo<'p> {
fn disable_peer(&mut self, _peer_id: PeerId) {
}
fn disconnect_peer(&mut self, _peer_id: PeerId) {
}
fn respond(&mut self, packet_id: PacketId, data: Vec<u8>) -> Result<(), UtilError> {
self.queue.push_back(TestPacket {
data: data,

View File

@ -83,11 +83,12 @@ impl<'a> fmt::Display for PrettySlice<'a> {
}
}
/// TODO [Gav Wood] Please document me
/// Trait to allow a type to be pretty-printed in `format!`, where unoverridable
/// defaults cannot otherwise be avoided.
pub trait ToPretty {
/// TODO [Gav Wood] Please document me
/// Convert a type into a derivative form in order to make `format!` print it prettily.
fn pretty(&self) -> PrettySlice;
/// TODO [Gav Wood] Please document me
/// Express the object as a hex string.
fn to_hex(&self) -> String {
format!("{}", self.pretty())
}
@ -110,11 +111,11 @@ impl ToPretty for Bytes {
}
}
/// TODO [debris] Please document me
/// A byte collection reference that can either be a slice or a vector
pub enum BytesRef<'a> {
/// TODO [debris] Please document me
/// This is a reference to a vector
Flexible(&'a mut Bytes),
/// TODO [debris] Please document me
/// This is a reference to a slice
Fixed(&'a mut [u8])
}
@ -144,11 +145,12 @@ pub type Bytes = Vec<u8>;
/// Slice of bytes to underlying memory
pub trait BytesConvertable {
// TODO: rename to as_slice
/// TODO [Gav Wood] Please document me
/// Get the underlying byte-wise representation of the value.
/// Deprecated - use `as_slice` instead.
fn bytes(&self) -> &[u8];
/// TODO [Gav Wood] Please document me
/// Get the underlying byte-wise representation of the value.
fn as_slice(&self) -> &[u8] { self.bytes() }
/// TODO [Gav Wood] Please document me
/// Get a copy of the underlying byte-wise representation.
fn to_bytes(&self) -> Bytes { self.as_slice().to_vec() }
}

View File

@ -49,9 +49,9 @@ use sha3::*;
/// index. Their `BloomIndex` can be created from block number and given level.
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub struct BloomIndex {
/// TODO [debris] Please document me
/// Bloom level
pub level: u8,
/// TODO [debris] Please document me
/// Filter Index
pub index: usize,
}

View File

@ -48,7 +48,7 @@ macro_rules! flushln {
($fmt:expr, $($arg:tt)*) => (flush!(concat!($fmt, "\n"), $($arg)*));
}
/// TODO [Gav Wood] Please document me
#[doc(hidden)]
pub fn flush(s: String) {
::std::io::stdout().write(s.as_bytes()).unwrap();
::std::io::stdout().flush().unwrap();

View File

@ -6,11 +6,12 @@ use uint::*;
use secp256k1::{key, Secp256k1};
use rand::os::OsRng;
/// TODO [Gav Wood] Please document me
/// Secret key for secp256k1 EC operations. 256 bit generic "hash" data.
pub type Secret = H256;
/// TODO [Gav Wood] Please document me
/// Public key for secp256k1 EC operations. 512 bit generic "hash" data.
pub type Public = H512;
/// TODO [Gav Wood] Please document me
/// Signature for secp256k1 EC operations; encodes two 256-bit curve points
/// and a third sign bit. 520 bit generic "hash" data.
pub type Signature = H520;
lazy_static! {
@ -38,17 +39,17 @@ impl Signature {
}
#[derive(Debug)]
/// TODO [arkpar] Please document me
/// Crypto error
pub enum CryptoError {
/// TODO [arkpar] Please document me
/// Invalid secret key
InvalidSecret,
/// TODO [arkpar] Please document me
/// Invalid public key
InvalidPublic,
/// TODO [arkpar] Please document me
/// Invalid EC signature
InvalidSignature,
/// TODO [arkpar] Please document me
/// Invalid AES message
InvalidMessage,
/// TODO [arkpar] Please document me
/// IO Error
Io(::std::io::Error),
}
@ -133,7 +134,7 @@ impl KeyPair {
pub fn sign(&self, message: &H256) -> Result<Signature, CryptoError> { ec::sign(&self.secret, message) }
}
/// TODO [arkpar] Please document me
/// EC functions
pub mod ec {
use hash::*;
use uint::*;
@ -210,12 +211,12 @@ pub mod ec {
}
}
/// TODO [arkpar] Please document me
/// ECDH functions
pub mod ecdh {
use crypto::*;
use crypto::{self};
/// TODO [arkpar] Please document me
/// Agree on a shared secret
pub fn agree(secret: &Secret, public: &Public, ) -> Result<Secret, CryptoError> {
use secp256k1::*;
let context = &crypto::SECP256K1;
@ -231,13 +232,13 @@ pub mod ecdh {
}
}
/// TODO [arkpar] Please document me
/// ECIES function
pub mod ecies {
use hash::*;
use bytes::*;
use crypto::*;
/// TODO [arkpar] Please document me
/// Encrypt a message with a public key
pub fn encrypt(public: &Public, plain: &[u8]) -> Result<Bytes, CryptoError> {
use ::rcrypto::digest::Digest;
use ::rcrypto::sha2::Sha256;
@ -273,7 +274,7 @@ pub mod ecies {
Ok(msg)
}
/// TODO [arkpar] Please document me
/// Decrypt a message with a secret key
pub fn decrypt(secret: &Secret, encrypted: &[u8]) -> Result<Bytes, CryptoError> {
use ::rcrypto::digest::Digest;
use ::rcrypto::sha2::Sha256;
@ -339,20 +340,20 @@ pub mod ecies {
}
}
/// TODO [arkpar] Please document me
/// AES encryption
pub mod aes {
use ::rcrypto::blockmodes::*;
use ::rcrypto::aessafe::*;
use ::rcrypto::symmetriccipher::*;
use ::rcrypto::buffer::*;
/// TODO [arkpar] Please document me
/// Encrypt a message
pub fn encrypt(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) {
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
}
/// TODO [arkpar] Please document me
/// Decrypt a message
pub fn decrypt(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");

View File

@ -6,36 +6,36 @@ use rlp::DecoderError;
use io;
#[derive(Debug)]
/// TODO [Gav Wood] Please document me
/// Error in database subsystem.
pub enum BaseDataError {
/// TODO [Gav Wood] Please document me
/// An entry was removed more times than inserted.
NegativelyReferencedHash,
}
#[derive(Debug)]
/// General error type which should be capable of representing all errors in ethcore.
pub enum UtilError {
/// TODO [Gav Wood] Please document me
/// Error concerning the crypto utility subsystem.
Crypto(::crypto::CryptoError),
/// TODO [Gav Wood] Please document me
/// Error concerning the Rust standard library's IO subsystem.
StdIo(::std::io::Error),
/// TODO [Gav Wood] Please document me
/// Error concerning our IO utility subsystem.
Io(io::IoError),
/// TODO [Gav Wood] Please document me
/// Error concerning the network address parsing subsystem.
AddressParse(::std::net::AddrParseError),
/// TODO [Gav Wood] Please document me
/// Error concerning the network address resolution subsystem.
AddressResolve(Option<::std::io::Error>),
/// TODO [Gav Wood] Please document me
/// Error concerning the hex conversion logic.
FromHex(FromHexError),
/// TODO [Gav Wood] Please document me
/// Error concerning the database abstraction logic.
BaseData(BaseDataError),
/// TODO [Gav Wood] Please document me
/// Error concerning the network subsystem.
Network(NetworkError),
/// TODO [Gav Wood] Please document me
/// Error concerning the RLP decoder.
Decoder(DecoderError),
/// TODO [Gav Wood] Please document me
/// Miscellaneous error described by a string.
SimpleString(String),
/// TODO [Gav Wood] Please document me
/// Error from a bad input size being given for the needed output.
BadSize,
}

View File

@ -9,8 +9,8 @@ macro_rules! xjson {
}
}
/// TODO [Gav Wood] Please document me
/// Trait allowing conversion from a JSON value.
pub trait FromJson {
/// TODO [Gav Wood] Please document me
/// Convert a JSON value to an instance of this type.
fn from_json(json: &Json) -> Self;
}

View File

@ -15,35 +15,35 @@ use serde;
///
/// Note: types implementing `FixedHash` must be also `BytesConvertable`.
pub trait FixedHash: Sized + BytesConvertable + Populatable + FromStr + Default {
/// TODO [Gav Wood] Please document me
/// Create a new, zero-initialised, instance.
fn new() -> Self;
/// Synonym for `new()`. Prefer to new as it's more readable.
fn zero() -> Self;
/// TODO [debris] Please document me
/// Create a new, cryptographically random, instance.
fn random() -> Self;
/// TODO [debris] Please document me
/// Assign self have a cryptographically random value.
fn randomize(&mut self);
/// TODO [arkpar] Please document me
fn size() -> usize;
/// TODO [arkpar] Please document me
/// Get the size of this object in bytes.
fn len() -> usize;
/// Convert a slice of bytes of length `len()` to an instance of this type.
fn from_slice(src: &[u8]) -> Self;
/// TODO [arkpar] Please document me
/// Assign self to be of the same value as a slice of bytes of length `len()`.
fn clone_from_slice(&mut self, src: &[u8]) -> usize;
/// TODO [Gav Wood] Please document me
/// Copy the data of this object into some mutable slice of length `len()`.
fn copy_to(&self, dest: &mut [u8]);
/// TODO [Gav Wood] Please document me
/// When interpreting self as a bloom output, augment (bit-wise OR) with the a bloomed version of `b`.
fn shift_bloomed<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash;
/// TODO [debris] Please document me
/// Same as `shift_bloomed` except that `self` is consumed and a new value returned.
fn with_bloomed<T>(mut self, b: &T) -> Self where T: FixedHash { self.shift_bloomed(b); self }
/// TODO [Gav Wood] Please document me
/// Bloom the current value using the bloom parameter `m`.
fn bloom_part<T>(&self, m: usize) -> T where T: FixedHash;
/// TODO [debris] Please document me
/// Check to see whether this hash, interpreted as a bloom, contains the value `b` when bloomed.
fn contains_bloomed<T>(&self, b: &T) -> bool where T: FixedHash;
/// TODO [arkpar] Please document me
/// Returns `true` if all bits set in `b` are also set in `self`.
fn contains<'a>(&'a self, b: &'a Self) -> bool;
/// TODO [debris] Please document me
/// Returns `true` if no bits are set.
fn is_zero(&self) -> bool;
/// Return the lowest 8 bytes interpreted as a BigEndian integer.
/// Returns the lowest 8 bytes interpreted as a BigEndian integer.
fn low_u64(&self) -> u64;
}
@ -58,7 +58,7 @@ fn clean_0x(s: &str) -> &str {
macro_rules! impl_hash {
($from: ident, $size: expr) => {
#[derive(Eq)]
/// TODO [Gav Wood] Please document me
/// Unformatted binary data of fixed length.
pub struct $from (pub [u8; $size]);
impl BytesConvertable for $from {
@ -103,7 +103,7 @@ macro_rules! impl_hash {
rng.fill_bytes(&mut self.0);
}
fn size() -> usize {
fn len() -> usize {
$size
}
@ -457,12 +457,12 @@ macro_rules! impl_hash {
}
impl $from {
/// TODO [Gav Wood] Please document me
/// Get a hex representation.
pub fn hex(&self) -> String {
format!("{:?}", self)
}
/// TODO [Gav Wood] Please document me
/// Construct new instance equal to the bloomed value of `b`.
pub fn from_bloomed<T>(b: &T) -> Self where T: FixedHash { b.bloom_part($size) }
}
@ -578,25 +578,27 @@ impl<'_> From<&'_ Address> for H256 {
}
}
/// TODO [Gav Wood] Please document me
/// Convert string `s` to an `H256`. Will panic if `s` is not 64 characters long or if any of
/// those characters are not 0-9, a-z or A-Z.
pub fn h256_from_hex(s: &str) -> H256 {
use std::str::FromStr;
H256::from_str(s).unwrap()
}
/// TODO [Gav Wood] Please document me
/// Convert `n` to an `H256`, setting the rightmost 8 bytes.
pub fn h256_from_u64(n: u64) -> H256 {
use uint::U256;
H256::from(&U256::from(n))
}
/// TODO [Gav Wood] Please document me
/// Convert string `s` to an `Address`. Will panic if `s` is not 40 characters long or if any of
/// those characters are not 0-9, a-z or A-Z.
pub fn address_from_hex(s: &str) -> Address {
use std::str::FromStr;
Address::from_str(s).unwrap()
}
/// TODO [Gav Wood] Please document me
/// Convert `n` to an `Address`, setting the rightmost 8 bytes.
pub fn address_from_u64(n: u64) -> Address {
let h256 = h256_from_u64(n);
From::from(h256)

View File

@ -42,9 +42,9 @@ mod worker;
use mio::{EventLoop, Token};
#[derive(Debug)]
/// TODO [arkpar] Please document me
/// IO Error
pub enum IoError {
/// TODO [arkpar] Please document me
/// Low level error from mio crate
Mio(::std::io::Error),
}
@ -78,19 +78,12 @@ pub trait IoHandler<Message>: Send + Sync where Message: Send + Sync + Clone + '
fn deregister_stream(&self, _stream: StreamToken, _event_loop: &mut EventLoop<IoManager<Message>>) {}
}
/// TODO [arkpar] Please document me
pub use io::service::TimerToken;
/// TODO [arkpar] Please document me
pub use io::service::StreamToken;
/// TODO [arkpar] Please document me
pub use io::service::IoContext;
/// TODO [arkpar] Please document me
pub use io::service::IoService;
/// TODO [arkpar] Please document me
pub use io::service::IoChannel;
/// TODO [arkpar] Please document me
pub use io::service::IoManager;
/// TODO [arkpar] Please document me
pub use io::service::TOKENS_PER_HANDLER;
#[cfg(test)]

View File

@ -1,6 +1,6 @@
use common::*;
/// TODO [Gav Wood] Please document me
/// Remove the `"0x"`, if present, from the left of `s`, returning the remaining slice.
pub fn clean(s: &str) -> &str {
if s.len() >= 2 && &s[0..2] == "0x" {
&s[2..]

View File

@ -107,14 +107,17 @@ impl MemoryDB {
self.data.get(key)
}
/// TODO [Gav Wood] Please document me
/// Return the internal map of hashes to data, clearing the current state.
pub fn drain(&mut self) -> HashMap<H256, (Bytes, i32)> {
let mut data = HashMap::new();
mem::swap(&mut self.data, &mut data);
data
}
/// TODO [Gav Wood] Please document me
/// Denote than an existing value has the given key. Used when a key gets removed without
/// a prior insert and thus has a negative reference with no value.
///
/// May safely be called even if the key's value is known, in which case it will be a no-op.
pub fn denote(&self, key: &H256, value: Bytes) -> &(Bytes, i32) {
if self.raw(key) == None {
unsafe {

View File

@ -5,13 +5,13 @@ use common::*;
#[derive(Debug,Clone,PartialEq,Eq)]
/// Diff type for specifying a change (or not).
pub enum Diff<T> where T: Eq {
/// TODO [Gav Wood] Please document me
/// Both sides are the same.
Same,
/// TODO [Gav Wood] Please document me
/// Left (pre, source) side doesn't include value, right side (post, destination) does.
Born(T),
/// TODO [Gav Wood] Please document me
/// Both sides include data; it chaged value between them.
Changed(T, T),
/// TODO [Gav Wood] Please document me
/// Left (pre, source) side does include value, right side (post, destination) does not.
Died(T),
}
@ -32,8 +32,8 @@ impl<T> Diff<T> where T: Eq {
#[derive(PartialEq,Eq,Clone,Copy)]
/// Boolean type for clean/dirty status.
pub enum Filth {
/// TODO [Gav Wood] Please document me
/// Data has not been changed.
Clean,
/// TODO [Gav Wood] Please document me
/// Data has been changed.
Dirty,
}

View File

@ -216,6 +216,12 @@ pub struct EncryptedConnection {
}
impl EncryptedConnection {
/// Get socket token
pub fn token(&self) -> StreamToken {
self.connection.token
}
/// Create an encrypted connection out of the handshake. Consumes a handshake object.
pub fn new(mut handshake: Handshake) -> Result<EncryptedConnection, UtilError> {
let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_public));

View File

@ -5,17 +5,17 @@ use rlp::*;
pub enum DisconnectReason
{
DisconnectRequested,
//TCPError,
//BadProtocol,
_TCPError,
_BadProtocol,
UselessPeer,
//TooManyPeers,
//DuplicatePeer,
//IncompatibleProtocol,
//NullIdentity,
//ClientQuit,
//UnexpectedIdentity,
//LocalIdentity,
//PingTimeout,
_TooManyPeers,
_DuplicatePeer,
_IncompatibleProtocol,
_NullIdentity,
_ClientQuit,
_UnexpectedIdentity,
_LocalIdentity,
PingTimeout,
}
#[derive(Debug)]

View File

@ -19,6 +19,7 @@ use io::*;
use network::NetworkProtocolHandler;
use network::node::*;
use network::stats::NetworkStats;
use network::error::DisconnectReason;
type Slab<T> = ::slab::Slab<T, usize>;
@ -108,6 +109,8 @@ pub enum NetworkIoMessage<Message> where Message: Send + Sync + Clone {
/// Timer delay in milliseconds.
delay: u64,
},
/// Disconnect a peer
Disconnect(PeerId),
/// User message
User(Message),
}
@ -181,8 +184,14 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone
}
/// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected.
pub fn disable_peer(&self, _peer: PeerId) {
pub fn disable_peer(&self, peer: PeerId) {
//TODO: remove capability, disconnect if no capabilities left
self.disconnect_peer(peer);
}
/// Disconnect peer. Reconnect can be attempted later.
pub fn disconnect_peer(&self, peer: PeerId) {
self.io.message(NetworkIoMessage::Disconnect(peer));
}
/// Register a new IO timer. 'IoHandler::timeout' will be called with the token.
@ -332,6 +341,7 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
}
fn maintain_network(&self, io: &IoContext<NetworkIoMessage<Message>>) {
self.keep_alive(io);
self.connect_peers(io);
}
@ -343,6 +353,21 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
self.connections.read().unwrap().iter().any(|e| match *e.lock().unwrap().deref() { ConnectionEntry::Handshake(ref h) => h.id.eq(&id), _ => false })
}
fn keep_alive(&self, io: &IoContext<NetworkIoMessage<Message>>) {
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() {
s.disconnect(DisconnectReason::PingTimeout);
to_kill.push(s.token());
}
}
}
for p in to_kill {
self.kill_connection(p, io);
}
}
fn connect_peers(&self, io: &IoContext<NetworkIoMessage<Message>>) {
struct NodeInfo {
id: NodeId,
@ -684,6 +709,15 @@ impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Messa
self.timers.write().unwrap().insert(handler_token, ProtocolTimer { protocol: protocol, token: *token });
io.register_timer(handler_token, *delay).expect("Error registering timer");
},
NetworkIoMessage::Disconnect(ref peer) => {
if let Some(connection) = self.connections.read().unwrap().get(*peer).cloned() {
match *connection.lock().unwrap().deref_mut() {
ConnectionEntry::Handshake(_) => {},
ConnectionEntry::Session(ref mut s) => { s.disconnect(DisconnectReason::DisconnectRequested); }
}
}
self.kill_connection(*peer, io);
},
NetworkIoMessage::User(ref message) => {
for (p, h) in self.handlers.read().unwrap().iter() {
h.message(&NetworkContext::new(io, p, None, self.connections.clone()), &message);

View File

@ -21,7 +21,7 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
let host = Arc::new(Host::new(config));
let stats = host.stats().clone();
let host_info = host.client_version();
info!("NetworkService::start(): id={:?}", host.client_id());
info!("Host ID={:?}", host.client_id());
try!(io_service.register_handler(host));
Ok(NetworkService {
io_service: io_service,

View File

@ -4,10 +4,14 @@ use rlp::*;
use network::connection::{EncryptedConnection, Packet};
use network::handshake::Handshake;
use error::*;
use io::{IoContext};
use io::{IoContext, StreamToken};
use network::error::{NetworkError, DisconnectReason};
use network::host::*;
use network::node::NodeId;
use time;
const PING_TIMEOUT_SEC: u64 = 30;
const PING_INTERVAL_SEC: u64 = 30;
/// Peer session over encrypted connection.
/// When created waits for Hello packet exchange and signals ready state.
@ -19,6 +23,8 @@ pub struct Session {
connection: EncryptedConnection,
/// Session ready flag. Set after successfull Hello packet exchange
had_hello: bool,
ping_time_ns: u64,
pong_time_ns: Option<u64>,
}
/// Structure used to report various session events.
@ -47,6 +53,8 @@ pub struct SessionInfo {
pub protocol_version: u32,
/// Peer protocol capabilities
capabilities: Vec<SessionCapabilityInfo>,
/// Peer ping delay in milliseconds
pub ping_ms: Option<u64>,
}
#[derive(Debug, PartialEq, Eq)]
@ -95,10 +103,13 @@ impl Session {
client_version: String::new(),
protocol_version: 0,
capabilities: Vec::new(),
ping_ms: None,
},
ping_time_ns: 0,
pong_time_ns: None,
};
try!(session.write_hello(host));
try!(session.write_ping());
try!(session.send_ping());
Ok(session)
}
@ -141,7 +152,7 @@ impl Session {
while protocol != self.info.capabilities[i].protocol {
i += 1;
if i == self.info.capabilities.len() {
debug!(target: "net", "Unkown protocol: {:?}", protocol);
debug!(target: "net", "Unknown protocol: {:?}", protocol);
return Ok(())
}
}
@ -152,6 +163,26 @@ impl Session {
self.connection.send_packet(&rlp.out())
}
/// Keep this session alive. Returns false if ping timeout happened
pub fn keep_alive(&mut self) -> bool {
let timed_out = if let Some(pong) = self.pong_time_ns {
pong - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000
} else {
time::precise_time_ns() - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000
};
if !timed_out && time::precise_time_ns() - self.ping_time_ns > PING_INTERVAL_SEC * 1000_000_000 {
if let Err(e) = self.send_ping() {
debug!("Error sending ping message: {:?}", e);
}
}
!timed_out
}
pub fn token(&self) -> StreamToken {
self.connection.token()
}
fn read_packet(&mut self, packet: Packet, host: &HostInfo) -> Result<SessionData, UtilError> {
if packet.data.len() < 2 {
return Err(From::from(NetworkError::BadProtocol));
@ -168,7 +199,12 @@ impl Session {
},
PACKET_DISCONNECT => Err(From::from(NetworkError::Disconnect(DisconnectReason::DisconnectRequested))),
PACKET_PING => {
try!(self.write_pong());
try!(self.send_pong());
Ok(SessionData::None)
},
PACKET_PONG => {
self.pong_time_ns = Some(time::precise_time_ns());
self.info.ping_ms = Some((self.pong_time_ns.unwrap() - self.ping_time_ns) / 1000_000);
Ok(SessionData::None)
},
PACKET_GET_PEERS => Ok(SessionData::None), //TODO;
@ -178,7 +214,7 @@ impl Session {
while packet_id < self.info.capabilities[i].id_offset {
i += 1;
if i == self.info.capabilities.len() {
debug!(target: "net", "Unkown packet: {:?}", packet_id);
debug!(target: "net", "Unknown packet: {:?}", packet_id);
return Ok(SessionData::None)
}
}
@ -189,7 +225,7 @@ impl Session {
Ok(SessionData::Packet { data: packet.data, protocol: protocol, packet_id: pid } )
},
_ => {
debug!(target: "net", "Unkown packet: {:?}", packet_id);
debug!(target: "net", "Unknown packet: {:?}", packet_id);
Ok(SessionData::None)
}
}
@ -255,15 +291,20 @@ impl Session {
Ok(())
}
fn write_ping(&mut self) -> Result<(), UtilError> {
self.send(try!(Session::prepare(PACKET_PING)))
/// Senf ping packet
pub fn send_ping(&mut self) -> Result<(), UtilError> {
try!(self.send(try!(Session::prepare(PACKET_PING))));
self.ping_time_ns = time::precise_time_ns();
self.pong_time_ns = None;
Ok(())
}
fn write_pong(&mut self) -> Result<(), UtilError> {
fn send_pong(&mut self) -> Result<(), UtilError> {
self.send(try!(Session::prepare(PACKET_PONG)))
}
fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError {
/// Disconnect this session
pub fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError {
let mut rlp = RlpStream::new();
rlp.append(&(PACKET_DISCONNECT as u32));
rlp.begin_list(1);

View File

@ -34,7 +34,7 @@ pub struct NibbleSlice<'a> {
offset_encode_suffix: usize,
}
/// TODO [Gav Wood] Please document me
/// Iterator type for a nibble slice.
pub struct NibbleSliceIterator<'a> {
p: &'a NibbleSlice<'a>,
i: usize,
@ -77,7 +77,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
(r, a.len() + b.len())
}*/
/// TODO [Gav Wood] Please document me
/// Get an iterator for the series of nibbles.
pub fn iter(&'a self) -> NibbleSliceIterator<'a> {
NibbleSliceIterator { p: self, i: 0 }
}
@ -132,7 +132,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
i
}
/// TODO [Gav Wood] Please document me
/// Encode while nibble slice in prefixed hex notation, noting whether it `is_leaf`.
pub fn encoded(&self, is_leaf: bool) -> Bytes {
let l = self.len();
let mut r = Bytes::with_capacity(l / 2 + 1);
@ -145,7 +145,8 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
r
}
/// TODO [Gav Wood] Please document me
/// Encode only the leftmost `n` bytes of the nibble slice in prefixed hex notation,
/// noting whether it `is_leaf`.
pub fn encoded_leftmost(&self, n: usize, is_leaf: bool) -> Bytes {
let l = min(self.len(), n);
let mut r = Bytes::with_capacity(l / 2 + 1);

View File

@ -140,9 +140,9 @@ impl <T>ToBytes for T where T: FixedHash {
/// Error returned when FromBytes conversation goes wrong
#[derive(Debug, PartialEq, Eq)]
pub enum FromBytesError {
/// TODO [debris] Please document me
/// Expected more RLP data
DataIsTooShort,
/// TODO [debris] Please document me
/// Extra bytes after the end of the last item
DataIsTooLong,
/// Integer-representation is non-canonically prefixed with zero byte(s).
ZeroPrefixedInt,
@ -165,7 +165,7 @@ pub type FromBytesResult<T> = Result<T, FromBytesError>;
///
/// TODO: check size of bytes before conversation and return appropriate error
pub trait FromBytes: Sized {
/// TODO [debris] Please document me
/// Create a value from bytes
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
}
@ -236,7 +236,7 @@ impl_uint_from_bytes!(U128);
impl <T>FromBytes for T where T: FixedHash {
fn from_bytes(bytes: &[u8]) -> FromBytesResult<T> {
match bytes.len().cmp(&T::size()) {
match bytes.len().cmp(&T::len()) {
Ordering::Less => return Err(FromBytesError::DataIsTooShort),
Ordering::Greater => return Err(FromBytesError::DataIsTooLong),
Ordering::Equal => ()
@ -246,7 +246,7 @@ impl <T>FromBytes for T where T: FixedHash {
use std::{mem, ptr};
let mut res: T = mem::uninitialized();
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::len());
Ok(res)
}

View File

@ -48,13 +48,13 @@ pub use self::rlpstream::{RlpStream};
pub use elastic_array::ElasticArray1024;
use super::hash::H256;
/// TODO [arkpar] Please document me
/// The RLP encoded empty data (used to mean "null value").
pub const NULL_RLP: [u8; 1] = [0x80; 1];
/// TODO [Gav Wood] Please document me
/// The RLP encoded empty list.
pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1];
/// TODO [arkpar] Please document me
/// The SHA3 of the RLP encoding of empty data.
pub const SHA3_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21] );
/// TODO [debris] Please document me
/// The SHA3 of the RLP encoding of empty list.
pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45, 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47] );
/// Shortcut function to decode trusted rlp

View File

@ -3,27 +3,27 @@ use std::error::Error as StdError;
use rlp::bytes::FromBytesError;
#[derive(Debug, PartialEq, Eq)]
/// TODO [debris] Please document me
/// Error concerning the RLP decoder.
pub enum DecoderError {
/// TODO [debris] Please document me
/// Couldn't convert given bytes to an instance of required type.
FromBytesError(FromBytesError),
/// Given data has additional bytes at the end of the valid RLP fragment.
/// Data has additional bytes at the end of the valid RLP fragment.
RlpIsTooBig,
/// TODO [debris] Please document me
/// Data has too few bytes for valid RLP.
RlpIsTooShort,
/// TODO [debris] Please document me
/// Expect an encoded list, RLP was something else.
RlpExpectedToBeList,
/// TODO [Gav Wood] Please document me
/// Expect encoded data, RLP was something else.
RlpExpectedToBeData,
/// TODO [Gav Wood] Please document me
/// Expected a different size list.
RlpIncorrectListLen,
/// TODO [Gav Wood] Please document me
/// Data length number has a prefixed zero byte, invalid for numbers.
RlpDataLenWithZeroPrefix,
/// TODO [Gav Wood] Please document me
/// List length number has a prefixed zero byte, invalid for numbers.
RlpListLenWithZeroPrefix,
/// TODO [debris] Please document me
/// Non-canonical (longer than necessary) representation used for data or list.
RlpInvalidIndirection,
/// Returned when declared length is inconsistent with data specified after
/// Declared length is inconsistent with data specified after.
RlpInconsistentLengthAndData
}

View File

@ -103,12 +103,12 @@ impl <'a, 'view> Rlp<'a> where 'a: 'view {
res.unwrap_or_else(|_| panic!())
}
/// TODO [debris] Please document me
/// Decode into an object
pub fn as_val<T>(&self) -> T where T: RlpDecodable {
Self::view_as_val(self)
}
/// TODO [debris] Please document me
/// Decode list item at given index into an object
pub fn val_at<T>(&self, index: usize) -> T where T: RlpDecodable {
Self::view_as_val(&self.at(index))
}

View File

@ -7,15 +7,15 @@ use elastic_array::ElasticArray1024;
use hash::H256;
use sha3::*;
/// TODO [debris] Please document me
/// Type is able to decode RLP.
pub trait Decoder: Sized {
/// TODO [debris] Please document me
/// Read a value from the RLP into a given type.
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
/// TODO [Gav Wood] Please document me
/// Get underlying `UntrustedRLP` object.
fn as_rlp(&self) -> &UntrustedRlp;
/// TODO [debris] Please document me
/// Get underlying raw bytes slice.
fn as_raw(&self) -> &[u8];
}
@ -31,17 +31,17 @@ pub trait RlpDecodable: Sized {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
}
/// TODO [debris] Please document me
/// A view into RLP encoded data
pub trait View<'a, 'view>: Sized {
/// TODO [debris] Please document me
/// RLP prototype type
type Prototype;
/// TODO [debris] Please document me
/// Payload info type
type PayloadInfo;
/// TODO [debris] Please document me
/// Data type
type Data;
/// TODO [debris] Please document me
/// Item type
type Item;
/// TODO [debris] Please document me
/// Iterator type
type Iter;
/// Creates a new instance of `Rlp` reader
@ -65,10 +65,10 @@ pub trait View<'a, 'view>: Sized {
/// Get the prototype of the RLP.
fn prototype(&self) -> Self::Prototype;
/// TODO [debris] Please document me
/// Get payload info.
fn payload_info(&self) -> Self::PayloadInfo;
/// TODO [debris] Please document me
/// Get underlieing data.
fn data(&'view self) -> Self::Data;
/// Returns number of RLP items.
@ -205,18 +205,18 @@ pub trait View<'a, 'view>: Sized {
/// ```
fn iter(&'view self) -> Self::Iter;
/// TODO [debris] Please document me
/// Decode data into an object
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable;
/// TODO [debris] Please document me
/// Decode data at given list index into an object
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable;
}
/// TODO [debris] Please document me
/// Raw RLP encoder
pub trait Encoder {
/// TODO [debris] Please document me
/// Write a value represented as bytes
fn emit_value<E: ByteEncodable>(&mut self, value: &E);
/// TODO [debris] Please document me
/// Write raw preencoded data to the output
fn emit_raw(&mut self, bytes: &[u8]) -> ();
}
@ -250,7 +250,7 @@ pub trait RlpEncodable {
fn rlp_append(&self, s: &mut RlpStream);
}
/// TODO [debris] Please document me
/// RLP encoding stream
pub trait Stream: Sized {
/// Initializes instance of empty `Stream`.
@ -341,7 +341,7 @@ pub trait Stream: Sized {
/// }
fn is_finished(&self) -> bool;
/// TODO [debris] Please document me
/// Get raw encoded bytes
fn as_raw(&self) -> &[u8];
/// Streams out encoded bytes.

View File

@ -21,21 +21,21 @@ impl OffsetCache {
}
#[derive(Debug)]
/// TODO [debris] Please document me
/// RLP prototype
pub enum Prototype {
/// TODO [debris] Please document me
/// Empty
Null,
/// TODO [debris] Please document me
/// Value
Data(usize),
/// TODO [debris] Please document me
/// List
List(usize),
}
/// Stores basic information about item
pub struct PayloadInfo {
/// TODO [debris] Please document me
/// Header length in bytes
pub header_len: usize,
/// TODO [debris] Please document me
/// Value length in bytes
pub value_len: usize,
}

View File

@ -6,7 +6,7 @@ use bytes::{BytesConvertable, Populatable};
use hash::{H256, FixedHash};
use self::sha3_ext::*;
/// TODO [Gav Wood] Please document me
/// Get the SHA3 (i.e. Keccak) hash of the empty bytes string.
pub const SHA3_EMPTY: H256 = H256( [0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70] );

View File

@ -36,7 +36,7 @@ use heapsize::HeapSizeOf;
/// Should be used to squeeze collections to certain size in bytes
pub trait Squeeze {
/// TODO [debris] Please document me
/// Try to reduce collection size to `size` bytes
fn squeeze(&mut self, size: usize);
}

View File

@ -1,19 +1,20 @@
//! Trie interface and implementation.
/// TODO [Gav Wood] Please document me
/// Export the trietraits module.
pub mod trietraits;
/// Export the standardmap module.
pub mod standardmap;
/// TODO [Gav Wood] Please document me
/// Export the journal module.
pub mod journal;
/// TODO [Gav Wood] Please document me
/// Export the node module.
pub mod node;
/// TODO [Gav Wood] Please document me
/// Export the triedb module.
pub mod triedb;
/// TODO [Gav Wood] Please document me
/// Export the triedbmut module.
pub mod triedbmut;
/// TODO [Gav Wood] Please document me
/// Export the sectriedb module.
pub mod sectriedb;
/// TODO [Gav Wood] Please document me
/// Export the sectriedbmut module.
pub mod sectriedbmut;
pub use self::trietraits::*;

View File

@ -7,13 +7,13 @@ use super::journal::*;
/// Type of node in the trie and essential information thereof.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Node<'a> {
/// TODO [Gav Wood] Please document me
/// Null trie node; could be an empty root or an empty branch entry.
Empty,
/// TODO [Gav Wood] Please document me
/// Leaf node; has key slice and value. Value may not be empty.
Leaf(NibbleSlice<'a>, &'a[u8]),
/// TODO [Gav Wood] Please document me
/// Extension node; has key slice and node data. Data may not be null.
Extension(NibbleSlice<'a>, &'a[u8]),
/// TODO [Gav Wood] Please document me
/// Branch node; has array of 16 child nodes (each possibly null) and an optional immediate node data.
Branch([&'a[u8]; 16], Option<&'a [u8]>)
}

View File

@ -7,13 +7,13 @@ use hash::*;
/// Alphabet to use when creating words for insertion into tries.
pub enum Alphabet {
/// TODO [Gav Wood] Please document me
/// All values are allowed in each bytes of the key.
All,
/// TODO [Gav Wood] Please document me
/// Only a 6 values ('a' - 'f') are chosen to compose the key.
Low,
/// TODO [Gav Wood] Please document me
/// Quite a few values (around 32) are chosen to compose the key.
Mid,
/// TODO [Gav Wood] Please document me
/// A set of bytes given is used to compose the key.
Custom(Bytes),
}

View File

@ -34,7 +34,7 @@ use super::node::*;
pub struct TrieDB<'db> {
db: &'db HashDB,
root: &'db H256,
/// TODO [Gav Wood] Please document me
/// The number of hashes performed so far in operations on this trie.
pub hash_count: usize,
}

View File

@ -40,7 +40,7 @@ use super::trietraits::*;
pub struct TrieDBMut<'db> {
db: &'db mut HashDB,
root: &'db mut H256,
/// TODO [Gav Wood] Please document me
/// The number of hashes performed so far in operations on this trie.
pub hash_count: usize,
}
@ -72,7 +72,7 @@ impl<'db> TrieDBMut<'db> {
// TODO: return Result<Self, TrieError>
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
if !db.exists(root) {
flush(format!("Trie root not found {}", root));
flushln!("Trie root not found {}", root);
panic!("Trie root not found!");
}
TrieDBMut {

View File

@ -60,20 +60,20 @@ macro_rules! panic_on_overflow {
}
}
/// TODO [Gav Wood] Please document me
/// Large, fixed-length unsigned integer type.
pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug + fmt::Display + PartialOrd + Ord + PartialEq + Eq + Hash {
/// Size of this type.
const SIZE: usize;
/// TODO [Gav Wood] Please document me
/// Returns new instance equalling zero.
fn zero() -> Self;
/// TODO [Gav Wood] Please document me
/// Returns new instance equalling one.
fn one() -> Self;
/// TODO [Gav Wood] Please document me
/// Error type for converting from a decimal string.
type FromDecStrErr;
/// TODO [Gav Wood] Please document me
/// Convert from a decimal string.
fn from_dec_str(value: &str) -> Result<Self, Self::FromDecStrErr>;
/// Conversion to u32
@ -104,26 +104,25 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug +
/// Return wrapped eponentation `self**other` and flag if there was an overflow
fn overflowing_pow(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Add this `Uint` to other returning result and possible overflow
fn overflowing_add(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Subtract another `Uint` from this returning result and possible overflow
fn overflowing_sub(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Multiple this `Uint` with other returning result and possible overflow
fn overflowing_mul(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Divide this `Uint` by other returning result and possible overflow
fn overflowing_div(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Returns reminder of division of this `Uint` by other and possible overflow
fn overflowing_rem(self, other: Self) -> (Self, bool);
/// TODO [debris] Please document me
/// Returns negation of this `Uint` and overflow (always true)
fn overflowing_neg(self) -> (Self, bool);
/// TODO [Gav Wood] Please document me
/// Shifts this `Uint` and returns overflow
fn overflowing_shl(self, shift: u32) -> (Self, bool);
}
@ -939,12 +938,10 @@ impl From<U256> for u32 {
}
}
/// TODO [Gav Wood] Please document me
/// Constant value of `U256::zero()` that can be used for a reference saving an additional instance creation.
pub const ZERO_U256: U256 = U256([0x00u64; 4]);
/// TODO [Gav Wood] Please document me
/// Constant value of `U256::one()` that can be used for a reference saving an additional instance creation.
pub const ONE_U256: U256 = U256([0x01u64, 0x00u64, 0x00u64, 0x00u64]);
/// TODO [Gav Wood] Please document me
pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);
#[cfg(test)]
mod tests {

View File

@ -13,7 +13,7 @@
/// }
/// ```
pub trait SharedPrefix <T> {
/// TODO [debris] Please document me
/// Get common prefix length
fn shared_prefix_len(&self, elem: &[T]) -> usize;
}