Merge branch 'master' into nvolf
This commit is contained in:
commit
f85b9eb75b
19
.travis.yml
19
.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 '<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
|
||||
|
38
README.md
38
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
|
||||
|
4
doc.sh
Executable file
4
doc.sh
Executable 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
|
@ -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" }
|
||||
|
@ -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() }
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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")]
|
||||
|
@ -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 {
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
pub mod ext;
|
||||
pub mod evm;
|
||||
/// TODO [Tomusdrw] Please document me
|
||||
pub mod interpreter;
|
||||
#[macro_use]
|
||||
pub mod factory;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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() }
|
||||
}
|
||||
|
||||
|
@ -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());
|
@ -1,6 +1,6 @@
|
||||
use client::{BlockChainClient,Client};
|
||||
use super::test_common::*;
|
||||
use super::helpers::*;
|
||||
use tests::helpers::*;
|
||||
|
||||
#[test]
|
||||
fn created() {
|
||||
@ -75,4 +75,4 @@ fn can_collect_garbage() {
|
||||
let client = client_result.reference();
|
||||
client.tick();
|
||||
assert!(client.cache_info().blocks < 100 * 1024);
|
||||
}
|
||||
}
|
@ -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)
|
@ -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> {
|
10
ethcore/src/json_tests/mod.rs
Normal file
10
ethcore/src/json_tests/mod.rs
Normal 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;
|
@ -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.)
|
@ -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);
|
||||
}
|
@ -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
|
||||
//! brew install rocksdb
|
||||
//! # 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:
|
||||
//!
|
||||
//! - llvm
|
||||
//! ```bash
|
||||
//! # install rocksdb && multirust
|
||||
//! brew update
|
||||
//! brew install rocksdb
|
||||
//! brew install multirust
|
||||
//!
|
||||
//! - download llvm 3.7 from http://llvm.org/apt/
|
||||
//! # install nightly and make it default
|
||||
//! multirust update nightly && multirust default nightly
|
||||
//!
|
||||
//! ```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
|
||||
//! # export rust LIBRARY_PATH
|
||||
//! export LIBRARY_PATH=/usr/local/lib
|
||||
//!
|
||||
//! - 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;
|
||||
//! # download and build parity
|
||||
//! git clone https://github.com/ethcore/parity
|
||||
//! cd parity
|
||||
//! cargo build --release
|
||||
//! ```
|
||||
|
||||
#[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;
|
||||
|
||||
#[cfg(test)]
|
||||
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;
|
||||
|
@ -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()))
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
@ -109,4 +111,4 @@ mod tests {
|
||||
let service = ClientService::start(spec, NetworkConfiguration::new());
|
||||
assert!(service.is_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
|
@ -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())
|
||||
|
@ -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());
|
||||
@ -57,4 +58,4 @@ mod tests {
|
||||
assert_eq!(sub_state.sstore_clears_count, x!(12));
|
||||
assert_eq!(sub_state.suicides.len(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use client::{BlockChainClient,Client};
|
||||
#[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();
|
||||
|
@ -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;
|
@ -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)));
|
||||
|
@ -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(())
|
||||
}
|
||||
|
2
hook.sh
2
hook.sh
@ -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
466
install-deps.sh
Executable 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
475
install-parity.sh
Executable 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
|
@ -13,4 +13,5 @@ ethcore = { path = ".." }
|
||||
clippy = "0.0.37"
|
||||
log = "0.3"
|
||||
env_logger = "0.3"
|
||||
time = "0.1.34"
|
||||
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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() }
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)]
|
||||
|
@ -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..]
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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));
|
||||
@ -607,4 +613,4 @@ mod tests {
|
||||
assert!(!status.is_ok());
|
||||
assert_eq!(1, connection.send_queue.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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] );
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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::*;
|
||||
|
@ -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]>)
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user