Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:ethcore/parity into user_default
Browse files Browse the repository at this point in the history
  • Loading branch information
debris committed Sep 5, 2016
2 parents 0e788d6 + 4e466f0 commit 7bd504b
Show file tree
Hide file tree
Showing 18 changed files with 545 additions and 164 deletions.
111 changes: 65 additions & 46 deletions ethcore/src/evm/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@

//! Evm interface.
use common::*;
use std::{ops, cmp, fmt};
use util::{U128, U256, U512, Uint};
use action_params::ActionParams;
use evm::Ext;

/// Evm errors.
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas.
/// The state should be reverted to the state from before the
Expand Down Expand Up @@ -63,6 +65,21 @@ pub enum Error {
Internal,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
let message = match *self {
OutOfGas => "Out of gas",
BadJumpDestination { .. } => "Bad jump destination",
BadInstruction { .. } => "Bad instruction",
StackUnderflow { .. } => "Stack underflow",
OutOfStack { .. } => "Out of stack",
Internal => "Internal error",
};
message.fmt(f)
}
}

/// A specialized version of Result over EVM errors.
pub type Result<T> = ::std::result::Result<T, Error>;

Expand Down Expand Up @@ -193,53 +210,55 @@ pub trait Evm {
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
}


#[test]
#[cfg(test)]
fn should_calculate_overflow_mul_shr_without_overflow() {
// given
let num = 1048576;

// when
let (res1, o1) = U256::from(num).overflow_mul_shr(U256::from(num), 20);
let (res2, o2) = num.overflow_mul_shr(num, 20);

// then
assert_eq!(res1, U256::from(num));
assert!(!o1);
assert_eq!(res2, num);
assert!(!o2);
}
mod tests {
use util::{U256, Uint};
use super::CostType;

#[test]
fn should_calculate_overflow_mul_shr_without_overflow() {
// given
let num = 1048576;

// when
let (res1, o1) = U256::from(num).overflow_mul_shr(U256::from(num), 20);
let (res2, o2) = num.overflow_mul_shr(num, 20);

// then
assert_eq!(res1, U256::from(num));
assert!(!o1);
assert_eq!(res2, num);
assert!(!o2);
}

#[test]
#[cfg(test)]
fn should_calculate_overflow_mul_shr_with_overflow() {
// given
let max = ::std::u64::MAX;
let num1 = U256([max, max, max, max]);
let num2 = ::std::usize::MAX;

// when
let (res1, o1) = num1.overflow_mul_shr(num1, 256);
let (res2, o2) = num2.overflow_mul_shr(num2, 64);

// then
assert_eq!(res2, num2 - 1);
assert!(o2);

assert_eq!(res1, !U256::zero() - U256::one());
assert!(o1);
}
#[test]
fn should_calculate_overflow_mul_shr_with_overflow() {
// given
let max = u64::max_value();
let num1 = U256([max, max, max, max]);
let num2 = usize::max_value();

#[test]
#[cfg(test)]
fn should_validate_u256_to_usize_conversion() {
// given
let v = U256::from(::std::usize::MAX) + U256::from(1);
// when
let (res1, o1) = num1.overflow_mul_shr(num1, 256);
let (res2, o2) = num2.overflow_mul_shr(num2, 64);

// when
let res = usize::from_u256(v);
// then
assert_eq!(res2, num2 - 1);
assert!(o2);

assert_eq!(res1, !U256::zero() - U256::one());
assert!(o1);
}

// then
assert!(res.is_err());
#[test]
fn should_validate_u256_to_usize_conversion() {
// given
let v = U256::from(usize::max_value()) + U256::from(1);

// when
let res = usize::from_u256(v);

// then
assert!(res.is_err());
}
}
6 changes: 3 additions & 3 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl<'a> Executive<'a> {
// just drain the whole gas
self.state.revert_snapshot();

tracer.trace_failed_call(trace_info, vec![]);
tracer.trace_failed_call(trace_info, vec![], evm::Error::OutOfGas.into());

Err(evm::Error::OutOfGas)
}
Expand Down Expand Up @@ -320,7 +320,7 @@ impl<'a> Executive<'a> {
trace_output,
traces
),
_ => tracer.trace_failed_call(trace_info, traces),
Err(e) => tracer.trace_failed_call(trace_info, traces, e.into()),
};

trace!(target: "executive", "substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
Expand Down Expand Up @@ -385,7 +385,7 @@ impl<'a> Executive<'a> {
created,
subtracer.traces()
),
_ => tracer.trace_failed_create(trace_info, subtracer.traces())
Err(e) => tracer.trace_failed_create(trace_info, subtracer.traces(), e.into())
};

self.enact_result(&res, substate, unconfirmed_substate);
Expand Down
88 changes: 88 additions & 0 deletions ethcore/src/snapshot/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,92 @@ impl SnapshotReader for LooseReader {

Ok(buf)
}
}

#[cfg(test)]
mod tests {
use devtools::RandomTempPath;
use util::sha3::Hashable;

use snapshot::ManifestData;
use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader};

const STATE_CHUNKS: &'static [&'static [u8]] = &[b"dog", b"cat", b"hello world", b"hi", b"notarealchunk"];
const BLOCK_CHUNKS: &'static [&'static [u8]] = &[b"hello!", b"goodbye!", b"abcdefg", b"hijklmnop", b"qrstuvwxy", b"and", b"z"];

#[test]
fn packed_write_and_read() {
let path = RandomTempPath::new();
let mut writer = PackedWriter::new(path.as_path()).unwrap();

let mut state_hashes = Vec::new();
let mut block_hashes = Vec::new();

for chunk in STATE_CHUNKS {
let hash = chunk.sha3();
state_hashes.push(hash.clone());
writer.write_state_chunk(hash, chunk).unwrap();
}

for chunk in BLOCK_CHUNKS {
let hash = chunk.sha3();
block_hashes.push(hash.clone());
writer.write_block_chunk(chunk.sha3(), chunk).unwrap();
}

let manifest = ManifestData {
state_hashes: state_hashes,
block_hashes: block_hashes,
state_root: b"notarealroot".sha3(),
block_number: 12345678987654321,
block_hash: b"notarealblock".sha3(),
};

writer.finish(manifest.clone()).unwrap();

let reader = PackedReader::new(path.as_path()).unwrap().unwrap();
assert_eq!(reader.manifest(), &manifest);

for hash in manifest.state_hashes.iter().chain(&manifest.block_hashes) {
reader.chunk(hash.clone()).unwrap();
}
}

#[test]
fn loose_write_and_read() {
let path = RandomTempPath::new();
let mut writer = LooseWriter::new(path.as_path().into()).unwrap();

let mut state_hashes = Vec::new();
let mut block_hashes = Vec::new();

for chunk in STATE_CHUNKS {
let hash = chunk.sha3();
state_hashes.push(hash.clone());
writer.write_state_chunk(hash, chunk).unwrap();
}

for chunk in BLOCK_CHUNKS {
let hash = chunk.sha3();
block_hashes.push(hash.clone());
writer.write_block_chunk(chunk.sha3(), chunk).unwrap();
}

let manifest = ManifestData {
state_hashes: state_hashes,
block_hashes: block_hashes,
state_root: b"notarealroot".sha3(),
block_number: 12345678987654321,
block_hash: b"notarealblock".sha3(),
};

writer.finish(manifest.clone()).unwrap();

let reader = LooseReader::new(path.as_path().into()).unwrap();
assert_eq!(reader.manifest(), &manifest);

for hash in manifest.state_hashes.iter().chain(&manifest.block_hashes) {
reader.chunk(hash.clone()).unwrap();
}
}
}
2 changes: 1 addition & 1 deletion ethcore/src/snapshot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,4 +653,4 @@ impl BlockRebuilder {
}
}
}
}
}
49 changes: 48 additions & 1 deletion ethcore/src/snapshot/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use util::kvdb::{Database, DatabaseConfig};
use util::snappy;

/// Statuses for restorations.
#[derive(PartialEq, Clone, Copy, Debug)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum RestorationStatus {
/// No restoration.
Inactive,
Expand Down Expand Up @@ -519,3 +519,50 @@ impl SnapshotService for Service {
.expect("snapshot service and io service are kept alive by client service; qed");
}
}

#[cfg(test)]
mod tests {
use service::ClientIoMessage;
use io::{IoService};
use devtools::RandomTempPath;
use tests::helpers::get_test_spec;
use util::journaldb::Algorithm;

use snapshot::ManifestData;
use super::*;

#[test]
fn sends_async_messages() {
let service = IoService::<ClientIoMessage>::start().unwrap();

let dir = RandomTempPath::new();
let mut dir = dir.as_path().to_owned();
dir.push("pruning");
dir.push("db");

let service = Service::new(
&get_test_spec(),
Algorithm::Archive,
dir,
service.channel()
).unwrap();

assert!(service.manifest().is_none());
assert!(service.chunk(Default::default()).is_none());
assert_eq!(service.status(), RestorationStatus::Inactive);
assert_eq!(service.chunks_done(), (0, 0));

let manifest = ManifestData {
state_hashes: vec![],
block_hashes: vec![],
state_root: Default::default(),
block_number: 0,
block_hash: Default::default(),
};

service.begin_restore(manifest);
service.abort_restore();
service.restore_state_chunk(Default::default(), vec![]);
service.restore_block_chunk(Default::default(), vec![]);
}
}
2 changes: 1 addition & 1 deletion ethcore/src/snapshot/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl StateProducer {
let new_accs = rng.gen::<u32>() % 5;

for _ in 0..new_accs {
let address_hash = H256::random();
let address_hash = H256(rng.gen());
let balance: usize = rng.gen();
let nonce: usize = rng.gen();
let acc = ::state::Account::new_basic(balance.into(), nonce.into()).rlp();
Expand Down
17 changes: 16 additions & 1 deletion ethcore/src/snapshot/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,19 @@
mod blocks;
mod state;

pub mod helpers;
pub mod helpers;

use super::ManifestData;

#[test]
fn manifest_rlp() {
let manifest = ManifestData {
block_hashes: Vec::new(),
state_hashes: Vec::new(),
block_number: 1234567,
state_root: Default::default(),
block_hash: Default::default(),
};
let raw = manifest.clone().into_rlp();
assert_eq!(ManifestData::from_rlp(&raw).unwrap(), manifest);
}
4 changes: 2 additions & 2 deletions ethcore/src/snapshot/tests/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use snapshot::{chunk_state, Progress, StateRebuilder};
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
use super::helpers::{compare_dbs, StateProducer};

use rand;
use rand::{XorShiftRng, SeedableRng};
use util::hash::H256;
use util::journaldb::{self, Algorithm};
use util::kvdb::{Database, DatabaseConfig};
Expand All @@ -33,7 +33,7 @@ use std::sync::Arc;
#[test]
fn snap_and_restore() {
let mut producer = StateProducer::new();
let mut rng = rand::thread_rng();
let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]);
let mut old_db = MemoryDB::new();
let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS);

Expand Down
Loading

0 comments on commit 7bd504b

Please sign in to comment.