diff --git a/.travis.yml b/.travis.yml
index 2663d0d8e..7589697af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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 '' > 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
diff --git a/README.md b/README.md
index f442338db..c223921f1 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/doc.sh b/doc.sh
new file mode 100755
index 000000000..2fd5ac20f
--- /dev/null
+++ b/doc.sh
@@ -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
diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml
index d9c80f3a3..be7652e17 100644
--- a/ethcore/Cargo.toml
+++ b/ethcore/Cargo.toml
@@ -10,12 +10,10 @@ authors = ["Ethcore "]
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" }
diff --git a/ethcore/src/account.rs b/ethcore/src/account.rs
index 409637d6f..63f86b171 100644
--- a/ethcore/src/account.rs
+++ b/ethcore/src/account.rs
@@ -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, 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> { self.storage_overlay.borrow() }
diff --git a/ethcore/src/account_diff.rs b/ethcore/src/account_diff.rs
index 1843c4381..86faf40de 100644
--- a/ethcore/src/account_diff.rs
+++ b/ethcore/src/account_diff.rs
@@ -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, // Allowed to be Same
- /// TODO [Gav Wood] Please document me
+ /// Change in balance, allowed to be `Diff::Same`.
+ pub balance: Diff,
+ /// Change in nonce, allowed to be `Diff::Same`.
pub nonce: Diff, // Allowed to be Same
- /// TODO [Gav Wood] Please document me
+ /// Change in code, allowed to be `Diff::Same`.
pub code: Diff, // Allowed to be Same
- /// TODO [Gav Wood] Please document me
- pub storage: BTreeMap>,// Not allowed to be Same
+ /// Change in storage, values are not allowed to be `Diff::Same`.
+ pub storage: BTreeMap>,
}
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 {
match (pre, post) {
(None, Some(x)) => Some(AccountDiff {
diff --git a/ethcore/src/basic_types.rs b/ethcore/src/basic_types.rs
index 3d6fc2609..49a5c9556 100644
--- a/ethcore/src/basic_types.rs
+++ b/ethcore/src/basic_types.rs
@@ -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,
}
diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs
index f8e8ef16f..a2de89d13 100644
--- a/ethcore/src/block.rs
+++ b/ethcore/src/block.rs
@@ -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,
- /// TODO [Gav Wood] Please document me
+ /// Block uncles.
pub uncles: &'a Vec,
-
- /// TODO [Gav Wood] Please document me
+ /// Transaction receipts.
pub receipts: &'a Vec,
- /// TODO [Gav Wood] Please document me
+ /// State.
pub state: &'a mut State,
}
@@ -394,4 +395,4 @@ mod tests {
assert_eq!(orig_db.keys(), db.keys());
assert!(orig_db.keys().iter().filter(|k| orig_db.get(k.0) != db.get(k.0)).next() == None);
}
-}
\ No newline at end of file
+}
diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs
index dabe047e9..1fe31ba19 100644
--- a/ethcore/src/block_queue.rs
+++ b/ethcore/src/block_queue.rs
@@ -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,
ready_signal: Arc,
empty: Arc,
- processing: HashSet
+ processing: RwLock>
}
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 {
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);
diff --git a/ethcore/src/blockchain.rs b/ethcore/src/blockchain.rs
index 1dea65ae7..e2ed54c19 100644
--- a/ethcore/src/blockchain.rs
+++ b/ethcore/src/blockchain.rs
@@ -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,
- /// 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
}
diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs
index 00d0bbeb5..297f734b5 100644
--- a/ethcore/src/builtin.rs
+++ b/ethcore/src/builtin.rs
@@ -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()) {
diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs
index ee9b658d8..03c03ab49 100644
--- a/ethcore/src/client.rs
+++ b/ethcore/src/client.rs
@@ -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 {
@@ -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)
}
diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs
index 1fb6ef0ca..7017989e7 100644
--- a/ethcore/src/engine.rs
+++ b/ethcore/src/engine.rs
@@ -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.
diff --git a/ethcore/src/env_info.rs b/ethcore/src/env_info.rs
index 8b037036e..7c0516d2a 100644
--- a/ethcore/src/env_info.rs
+++ b/ethcore/src/env_info.rs
@@ -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 {
@@ -97,4 +90,4 @@ r#"
assert_eq!(default_env_info.difficulty, x!(0));
}
-}
\ No newline at end of file
+}
diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs
index 4ca988679..2d6753e95 100644
--- a/ethcore/src/error.rs
+++ b/ethcore/src/error.rs
@@ -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 {
- /// 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 {
- /// TODO [Gav Wood] Please document me
+ /// Minimum allowed value.
pub min: Option,
- /// TODO [Gav Wood] Please document me
+ /// Maximum allowed value.
pub max: Option,
- /// TODO [Gav Wood] Please document me
+ /// Value found.
pub found: T,
}
@@ -29,11 +29,10 @@ pub struct OutOfBounds {
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),
}
#[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),
- /// TODO [Gav Wood] Please document me
- UncleWrongGeneration,
- /// TODO [Gav Wood] Please document me
+ /// Extra data is of an invalid length.
ExtraDataOutOfBounds(OutOfBounds),
- /// TODO [arkpar] Please document me
+ /// Seal is incorrect format.
InvalidSealArity(Mismatch),
- /// TODO [arkpar] Please document me
+ /// Block has too much gas used.
TooMuchGasUsed(OutOfBounds),
- /// TODO [arkpar] Please document me
+ /// Uncles hash in header is invalid.
InvalidUnclesHash(Mismatch),
- /// TODO [arkpar] Please document me
+ /// An uncle is from a generation too old.
UncleTooOld(OutOfBounds),
- /// TODO [arkpar] Please document me
+ /// An uncle is from the same generation as the block.
UncleIsBrother(OutOfBounds),
- /// 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),
- /// TODO [arkpar] Please document me
+ /// Gas used header field is invalid.
InvalidGasUsed(Mismatch),
- /// TODO [arkpar] Please document me
+ /// Transactions root header field is invalid.
InvalidTransactionsRoot(Mismatch),
- /// 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),
+ /// Difficulty header field is invalid; this is a strong error used after getting a definitive
+ /// value for difficulty (which is provided).
InvalidDifficulty(Mismatch),
- /// 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),
+ /// Proof-of-work aspect of seal, which we assume is a 256-bit value, is invalid.
+ InvalidProofOfWork(OutOfBounds),
+ /// Gas limit header field is invalid.
InvalidGasLimit(OutOfBounds),
- /// TODO [arkpar] Please document me
- InvalidReceiptsStateRoot(Mismatch),
- /// TODO [arkpar] Please document me
+ /// Receipts trie root header field is invalid.
+ InvalidReceiptsRoot(Mismatch),
+ /// Timestamp header field is invalid.
InvalidTimestamp(OutOfBounds),
- /// TODO [arkpar] Please document me
+ /// Log bloom header field is invalid.
InvalidLogBloom(Mismatch),
- /// TODO [arkpar] Please document me
- InvalidEthashDifficulty(Mismatch),
- /// TODO [arkpar] Please document me
- InvalidBlockNonce(Mismatch),
- /// 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),
- /// TODO [arkpar] Please document me
+ /// Number field of header is invalid.
InvalidNumber(Mismatch),
/// Block number isn't sensible.
RidiculousNumber(OutOfBounds),
- /// 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),
- /// 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 for ImportError {
@@ -152,15 +157,15 @@ pub type ImportResult = Result;
#[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),
}
diff --git a/ethcore/src/ethereum/denominations.rs b/ethcore/src/ethereum/denominations.rs
index 093be89a7..2ab66431d 100644
--- a/ethcore/src/ethereum/denominations.rs
+++ b/ethcore/src/ethereum/denominations.rs
@@ -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) }
diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs
index ce40c5f42..e9aedc128 100644
--- a/ethcore/src/ethereum/ethash.rs
+++ b/ethcore/src/ethereum/ethash.rs
@@ -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 {
Box::new(Ethash {
spec: spec,
@@ -110,16 +110,18 @@ impl Engine for Ethash {
try!(UntrustedRlp::new(&header.seal[0]).as_val::());
try!(UntrustedRlp::new(&header.seal[1]).as_val::());
+ // 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(())
}
diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs
index c32fc40c6..ec6cfe103 100644
--- a/ethcore/src/ethereum/mod.rs
+++ b/ethcore/src/ethereum/mod.rs
@@ -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::*;
diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs
index b90ea5f97..f011f67a4 100644
--- a/ethcore/src/evm/evm.rs
+++ b/ethcore/src/evm/evm.rs
@@ -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
- wanted: usize,
- /// TODO [Tomusdrw] Please document me
+ /// How many stack elements instruction wanted to push
+ wanted: usize,
+ /// 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,
}
diff --git a/ethcore/src/evm/factory.rs b/ethcore/src/evm/factory.rs
index 9f76d25ec..bd9315e7f 100644
--- a/ethcore/src/evm/factory.rs
+++ b/ethcore/src/evm/factory.rs
@@ -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 {
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 {
+ 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 {
- Box::new(super::jit::JitEvm)
- }
-
- #[cfg(not(feature = "jit"))]
- fn jit() -> Box {
- 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")]
diff --git a/ethcore/src/evm/interpreter.rs b/ethcore/src/evm/interpreter.rs
index f55b94adb..6516d9946 100644
--- a/ethcore/src/evm/interpreter.rs
+++ b/ethcore/src/evm/interpreter.rs
@@ -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 {
diff --git a/ethcore/src/evm/mod.rs b/ethcore/src/evm/mod.rs
index 1426bc281..2ed9a1146 100644
--- a/ethcore/src/evm/mod.rs
+++ b/ethcore/src/evm/mod.rs
@@ -2,7 +2,6 @@
pub mod ext;
pub mod evm;
-/// TODO [Tomusdrw] Please document me
pub mod interpreter;
#[macro_use]
pub mod factory;
diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs
index d448ccb3a..0bc57433f 100644
--- a/ethcore/src/evm/tests.rs
+++ b/ethcore/src/evm/tests.rs
@@ -1,25 +1,45 @@
use common::*;
use evm;
use evm::{Ext, Schedule, Factory, VMType, ContractCreateResult, MessageCallResult};
+use std::fmt::Debug;
struct FakeLogEntry {
topics: Vec,
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,
+ receive_address: Option,
+ value: Option,
+ data: Bytes,
+ code_address: Option
+}
+
/// Fake externalities test structure.
///
/// Can't do recursive calls.
#[derive(Default)]
struct FakeExt {
+ sstore_clears: usize,
+ depth: usize,
store: HashMap,
- _balances: HashMap,
blockhashes: HashMap,
codes: HashMap,
logs: Vec,
_suicides: HashSet,
info: EnvInfo,
- schedule: Schedule
+ schedule: Schedule,
+ balances: HashMap,
+ calls: HashSet
}
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,
- _data: &[u8],
- _code_address: &Address,
+ gas: &U256,
+ sender_address: &Address,
+ receive_address: &Address,
+ value: Option,
+ 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(set: &HashSet, 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());
}
diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs
index d824ccc2c..b67b71306 100644
--- a/ethcore/src/executive.rs
+++ b/ethcore/src/executive.rs
@@ -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();
diff --git a/ethcore/src/extras.rs b/ethcore/src/extras.rs
index 4459826cc..4c54c6b27 100644
--- a/ethcore/src/extras.rs
+++ b/ethcore/src/extras.rs
@@ -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(&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(&self, hash: &K) -> Option where
T: ExtrasIndexable + Decodable,
K: ExtrasSliceConvertable;
- /// TODO [debris] Please document me
+ /// Check if extra data exists in the db
fn extras_exists(&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
}
@@ -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
}
@@ -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
}
diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs
index c6c18bf4b..b188a6bcf 100644
--- a/ethcore/src/header.rs
+++ b/ethcore/src/header.rs
@@ -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,
- /// TODO [arkpar] Please document me
+ /// The memoized hash of the RLP representation *including* the seal fields.
pub hash: RefCell