Merge with master

This commit is contained in:
Anton Gavrilov 2017-08-02 17:24:34 +02:00
commit 01ea968d4f
158 changed files with 14603 additions and 959 deletions

73
Cargo.lock generated
View File

@ -1,6 +1,15 @@
[root] [root]
name = "using_queue" name = "wasm"
version = "0.1.0" version = "0.1.0"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
]
[[package]] [[package]]
name = "advapi32-sys" name = "advapi32-sys"
@ -181,6 +190,14 @@ name = "blastfig"
version = "0.3.3" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bloomable"
version = "0.1.0"
dependencies = [
"ethcore-bigint 0.1.3",
"tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bloomchain" name = "bloomchain"
version = "0.1.0" version = "0.1.0"
@ -220,6 +237,15 @@ name = "cfg-if"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chainspec"
version = "0.1.0"
dependencies = [
"ethjson 0.1.0",
"serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cid" name = "cid"
version = "0.2.2" version = "0.2.2"
@ -271,6 +297,7 @@ dependencies = [
name = "common-types" name = "common-types"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bloomable 0.1.0",
"ethcore-util 1.8.0", "ethcore-util 1.8.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"rlp 0.2.0", "rlp 0.2.0",
@ -462,6 +489,7 @@ name = "ethcore"
version = "1.8.0" version = "1.8.0"
dependencies = [ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bloomable 0.1.0",
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bn 0.4.4 (git+https://github.com/paritytech/bn)", "bn 0.4.4 (git+https://github.com/paritytech/bn)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -502,8 +530,12 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stats 0.1.0", "stats 0.1.0",
"table 0.1.0",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"using_queue 0.1.0",
"vm 0.1.0",
"wasm 0.1.0",
] ]
[[package]] [[package]]
@ -625,6 +657,7 @@ dependencies = [
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stats 0.1.0", "stats 0.1.0",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
] ]
[[package]] [[package]]
@ -752,11 +785,9 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"sha3 0.1.0", "sha3 0.1.0",
"table 0.1.0",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"using_queue 0.1.0",
"vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -880,6 +911,7 @@ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0", "common-types 0.1.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0", "ethcore-util 1.8.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"evmjit 1.8.0", "evmjit 1.8.0",
@ -888,6 +920,7 @@ dependencies = [
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0", "rlp 0.2.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)", "wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
] ]
@ -903,6 +936,7 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
] ]
[[package]] [[package]]
@ -1933,7 +1967,6 @@ dependencies = [
"ethkey 0.2.0", "ethkey 0.2.0",
"ethstore 0.1.0", "ethstore 0.1.0",
"ethsync 1.8.0", "ethsync 1.8.0",
"evm 0.1.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1962,6 +1995,7 @@ dependencies = [
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
] ]
[[package]] [[package]]
@ -2018,7 +2052,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-precompiled" name = "parity-ui-precompiled"
version = "1.4.0" version = "1.4.0"
source = "git+https://github.com/paritytech/js-precompiled.git#5a357d01c459d3f371a87bfa138567b30603222c" source = "git+https://github.com/paritytech/js-precompiled.git#06f77d96f1b1a771d643f07b60c802d448b6415c"
dependencies = [ dependencies = [
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2567,6 +2601,14 @@ dependencies = [
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "serde_ignored"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.2" version = "1.0.2"
@ -3044,6 +3086,10 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "using_queue"
version = "0.1.0"
[[package]] [[package]]
name = "utf8-ranges" name = "utf8-ranges"
version = "1.0.0" version = "1.0.0"
@ -3072,6 +3118,20 @@ dependencies = [
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "vm"
version = "0.1.0"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"ethcore-util 1.8.0",
"ethjson 0.1.0",
"evmjit 1.8.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
]
[[package]] [[package]]
name = "void" name = "void"
version = "1.0.2" version = "1.0.2"
@ -3080,7 +3140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "wasm-utils" name = "wasm-utils"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/wasm-utils#fee06b6d5826c2dc1fc1aa183b0c2c75e3e140c3" source = "git+https://github.com/paritytech/wasm-utils#9462bcc0680f0ec2c876abdf75bae981dd4344a5"
dependencies = [ dependencies = [
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3355,6 +3415,7 @@ dependencies = [
"checksum serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a" "checksum serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a"
"checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639" "checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
"checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
"checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" "checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"

View File

@ -110,4 +110,4 @@ lto = false
panic = "abort" panic = "abort"
[workspace] [workspace]
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper"] members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec"]

9
chainspec/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "chainspec"
version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
[dependencies]
ethjson = { path = "../json" }
serde_json = "1.0"
serde_ignored = "0.0.4"

48
chainspec/src/main.rs Normal file
View File

@ -0,0 +1,48 @@
extern crate serde_json;
extern crate serde_ignored;
extern crate ethjson;
use std::collections::BTreeSet;
use std::{fs, env, process};
use ethjson::spec::Spec;
fn quit(s: &str) -> ! {
println!("{}", s);
process::exit(1);
}
fn main() {
let mut args = env::args();
if args.len() != 2 {
quit("You need to specify chainspec.json\n\
\n\
./chainspec <chainspec.json>");
}
let path = args.nth(1).expect("args.len() == 2; qed");
let file = match fs::File::open(&path) {
Ok(file) => file,
Err(_) => quit(&format!("{} could not be opened", path)),
};
let mut unused = BTreeSet::new();
let mut deserializer = serde_json::Deserializer::from_reader(file);
let spec: Result<Spec, _> = serde_ignored::deserialize(&mut deserializer, |field| {
unused.insert(field.to_string());
});
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
if !unused.is_empty() {
let err = unused.into_iter()
.map(|field| format!("{} unexpected field `{}`", path, field))
.collect::<Vec<_>>()
.join("\n");
quit(&err);
}
println!("{} is valid", path);
}

View File

@ -33,13 +33,14 @@
use std::io; use std::io;
use std::{fmt, mem, time}; use std::{fmt, mem, time};
use std::sync::Arc;
use std::collections::VecDeque; use std::collections::VecDeque;
use futures::{self, Future, BoxFuture}; use futures::{self, Future, BoxFuture};
use futures_cpupool::CpuPool; use futures_cpupool::CpuPool;
use ntp; use ntp;
use time::{Duration, Timespec}; use time::{Duration, Timespec};
use util::{Arc, RwLock}; use util::RwLock;
/// Time checker error. /// Time checker error.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]

View File

@ -53,6 +53,11 @@ semver = "0.6"
stats = { path = "../util/stats" } stats = { path = "../util/stats" }
time = "0.1" time = "0.1"
transient-hashmap = "0.4" transient-hashmap = "0.4"
using_queue = { path = "../util/using_queue" }
table = { path = "../util/table" }
bloomable = { path = "../util/bloomable" }
vm = { path = "vm" }
wasm = { path = "wasm" }
[dev-dependencies] [dev-dependencies]
native-contracts = { path = "native_contracts", features = ["test_contracts"] } native-contracts = { path = "native_contracts", features = ["test_contracts"] }

View File

@ -13,7 +13,9 @@ ethjson = { path = "../../json" }
lazy_static = "0.2" lazy_static = "0.2"
log = "0.3" log = "0.3"
rlp = { path = "../../util/rlp" } rlp = { path = "../../util/rlp" }
vm = { path = "../vm" }
parity-wasm = "0.12" parity-wasm = "0.12"
ethcore-logger = { path = "../../logger" }
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
[dev-dependencies] [dev-dependencies]

View File

@ -25,7 +25,7 @@ extern crate test;
use self::test::{Bencher, black_box}; use self::test::{Bencher, black_box};
use util::*; use util::*;
use evm::action_params::ActionParams; use vm::ActionParams;
use evm::{self, Factory, VMType}; use evm::{self, Factory, VMType};
use evm::tests::FakeExt; use evm::tests::FakeExt;

View File

@ -17,142 +17,8 @@
//! Evm interface. //! Evm interface.
use std::{ops, cmp, fmt}; use std::{ops, cmp, fmt};
use util::{U128, U256, U512, trie}; use util::{U128, U256, U512};
use action_params::ActionParams; use vm::{Ext, Result, ReturnData, GasLeft, Error};
use {Ext};
use super::wasm;
/// Evm errors.
#[derive(Debug, Clone, PartialEq)]
pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas.
/// The state should be reverted to the state from before the
/// transaction execution. But it does not mean that transaction
/// was invalid. Balance still should be transfered and nonce
/// should be increased.
OutOfGas,
/// `BadJumpDestination` is returned when execution tried to move
/// to position that wasn't marked with JUMPDEST instruction
BadJumpDestination {
/// Position the code tried to jump to.
destination: usize
},
/// `BadInstructions` is returned when given instruction is not supported
BadInstruction {
/// Unrecognized opcode
instruction: u8,
},
/// `StackUnderflow` when there is not enough stack elements to execute instruction
StackUnderflow {
/// Invoked instruction
instruction: &'static str,
/// How many stack elements was requested by instruction
wanted: usize,
/// How many elements were on stack
on_stack: usize
},
/// When execution would exceed defined Stack Limit
OutOfStack {
/// Invoked instruction
instruction: &'static str,
/// How many stack elements instruction wanted to push
wanted: usize,
/// What was the stack limit
limit: usize
},
/// Built-in contract failed on given input
BuiltIn(&'static str),
/// When execution tries to modify the state in static context
MutableCallInStaticContext,
/// Likely to cause consensus issues.
Internal(String),
/// Wasm runtime error
Wasm(String),
}
impl From<Box<trie::TrieError>> for Error {
fn from(err: Box<trie::TrieError>) -> Self {
Error::Internal(format!("Internal error: {}", err))
}
}
impl From<wasm::RuntimeError> for Error {
fn from(err: wasm::RuntimeError) -> Self {
Error::Wasm(format!("Runtime error: {:?}", err))
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match *self {
OutOfGas => write!(f, "Out of gas"),
BadJumpDestination { destination } => write!(f, "Bad jump destination {:x}", destination),
BadInstruction { instruction } => write!(f, "Bad instruction {:x}", instruction),
StackUnderflow { instruction, wanted, on_stack } => write!(f, "Stack underflow {} {}/{}", instruction, wanted, on_stack),
OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
Internal(ref msg) => write!(f, "Internal error: {}", msg),
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
}
}
}
/// A specialized version of Result over EVM errors.
pub type Result<T> = ::std::result::Result<T, Error>;
/// Return data buffer. Holds memory from a previous call and a slice into that memory.
#[derive(Debug)]
pub struct ReturnData {
mem: Vec<u8>,
offset: usize,
size: usize,
}
impl ::std::ops::Deref for ReturnData {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.mem[self.offset..self.offset + self.size]
}
}
impl ReturnData {
/// Create empty `ReturnData`.
pub fn empty() -> Self {
ReturnData {
mem: Vec::new(),
offset: 0,
size: 0,
}
}
/// Create `ReturnData` from give buffer and slice.
pub fn new(mem: Vec<u8>, offset: usize, size: usize) -> Self {
ReturnData {
mem: mem,
offset: offset,
size: size,
}
}
}
/// Gas Left: either it is a known value, or it needs to be computed by processing
/// a return instruction.
#[derive(Debug)]
pub enum GasLeft {
/// Known gas left
Known(U256),
/// Return or Revert instruction must be processed.
NeedsReturn {
/// Amount of gas left.
gas_left: U256,
/// Return data buffer.
data: ReturnData,
/// Apply or revert state changes on revert.
apply_state: bool
},
}
/// Finalization result. Gas Left: either it is a known value, or it needs to be computed by processing /// Finalization result. Gas Left: either it is a known value, or it needs to be computed by processing
/// a return instruction. /// a return instruction.
@ -281,15 +147,6 @@ impl CostType for usize {
} }
} }
/// Evm interface
pub trait Evm {
/// This function should be used to execute transaction.
///
/// It returns either an error, a known amount of gas left, or parameters to be used
/// to compute the final gas left.
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::U256; use util::U256;

View File

@ -17,7 +17,7 @@
//! Evm factory. //! Evm factory.
//! //!
use std::sync::Arc; use std::sync::Arc;
use evm::Evm; use vm::Vm;
use util::U256; use util::U256;
use super::interpreter::SharedCache; use super::interpreter::SharedCache;
use super::vmtype::VMType; use super::vmtype::VMType;
@ -33,7 +33,7 @@ impl Factory {
/// Create fresh instance of VM /// Create fresh instance of VM
/// Might choose implementation depending on supplied gas. /// Might choose implementation depending on supplied gas.
#[cfg(feature = "jit")] #[cfg(feature = "jit")]
pub fn create(&self, gas: U256) -> Box<Evm> { pub fn create(&self, gas: U256) -> Box<Vm> {
match self.evm { match self.evm {
VMType::Jit => { VMType::Jit => {
Box::new(super::jit::JitEvm::default()) Box::new(super::jit::JitEvm::default())
@ -49,7 +49,7 @@ impl Factory {
/// Create fresh instance of VM /// Create fresh instance of VM
/// Might choose implementation depending on supplied gas. /// Might choose implementation depending on supplied gas.
#[cfg(not(feature = "jit"))] #[cfg(not(feature = "jit"))]
pub fn create(&self, gas: U256) -> Box<Evm> { pub fn create(&self, gas: U256) -> Box<Vm> {
match self.evm { match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) { VMType::Interpreter => if Self::can_fit_in_usize(gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone())) Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))

View File

@ -14,18 +14,19 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::cmp;
use util::*; use util::*;
use super::u256_to_address; use super::u256_to_address;
use {evm, ext}; use {evm, vm};
use instructions::{self, Instruction, InstructionInfo}; use instructions::{self, Instruction, InstructionInfo};
use interpreter::stack::Stack; use interpreter::stack::Stack;
use schedule::Schedule; use vm::Schedule;
macro_rules! overflowing { macro_rules! overflowing {
($x: expr) => {{ ($x: expr) => {{
let (v, overflow) = $x; let (v, overflow) = $x;
if overflow { return Err(evm::Error::OutOfGas); } if overflow { return Err(vm::Error::OutOfGas); }
v v
}} }}
} }
@ -59,16 +60,16 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
} }
} }
pub fn verify_gas(&self, gas_cost: &Gas) -> evm::Result<()> { pub fn verify_gas(&self, gas_cost: &Gas) -> vm::Result<()> {
match &self.current_gas < gas_cost { match &self.current_gas < gas_cost {
true => Err(evm::Error::OutOfGas), true => Err(vm::Error::OutOfGas),
false => Ok(()) false => Ok(())
} }
} }
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation /// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
/// and that we `requested` some. /// and that we `requested` some.
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> evm::Result<Gas> { pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> vm::Result<Gas> {
// Try converting requested gas to `Gas` (`U256/u64`) // Try converting requested gas to `Gas` (`U256/u64`)
// but in EIP150 even if we request more we should never fail from OOG // but in EIP150 even if we request more we should never fail from OOG
let requested = requested.map(Gas::from_u256); let requested = requested.map(Gas::from_u256);
@ -82,7 +83,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
}; };
if let Some(Ok(r)) = requested { if let Some(Ok(r)) = requested {
Ok(min(r, max_gas_provided)) Ok(cmp::min(r, max_gas_provided))
} else { } else {
Ok(max_gas_provided) Ok(max_gas_provided)
} }
@ -107,12 +108,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
/// it will be the amount of gas that the current context provides to the child context. /// it will be the amount of gas that the current context provides to the child context.
pub fn requirements( pub fn requirements(
&mut self, &mut self,
ext: &ext::Ext, ext: &vm::Ext,
instruction: Instruction, instruction: Instruction,
info: &InstructionInfo, info: &InstructionInfo,
stack: &Stack<U256>, stack: &Stack<U256>,
current_mem_size: usize, current_mem_size: usize,
) -> evm::Result<InstructionRequirements<Gas>> { ) -> vm::Result<InstructionRequirements<Gas>> {
let schedule = ext.schedule(); let schedule = ext.schedule();
let tier = instructions::get_tier_idx(info.tier); let tier = instructions::get_tier_idx(info.tier);
let default_gas = Gas::from(schedule.tier_step_gas[tier]); let default_gas = Gas::from(schedule.tier_step_gas[tier]);
@ -291,7 +292,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
}) })
} }
fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> { fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> vm::Result<(Gas, Gas, usize)> {
let gas_for_mem = |mem_size: Gas| { let gas_for_mem = |mem_size: Gas| {
let s = mem_size >> 5; let s = mem_size >> 5;
// s * memory_gas + s * s / quad_coeff_div // s * memory_gas + s * s / quad_coeff_div
@ -319,12 +320,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
#[inline] #[inline]
fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> evm::Result<Gas> { fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> vm::Result<Gas> {
Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add)))) Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add))))
} }
#[inline] #[inline]
fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> { fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> vm::Result<Gas> {
if size.is_zero() { if size.is_zero() {
return Ok(Gas::from(0)); return Ok(Gas::from(0));
} }

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::U256; use util::U256;
use {ReturnData}; use vm::ReturnData;
const MAX_RETURN_WASTE_BYTES: usize = 16384; const MAX_RETURN_WASTE_BYTES: usize = 16384;

View File

@ -23,17 +23,23 @@ mod stack;
mod memory; mod memory;
mod shared_cache; mod shared_cache;
use std::marker::PhantomData;
use std::{cmp, mem};
use std::sync::Arc;
use vm::{
self, ActionParams, ActionValue, CallType, MessageCallResult,
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft
};
use evm::CostType;
use instructions::{self, Instruction, InstructionInfo};
use self::gasometer::Gasometer; use self::gasometer::Gasometer;
use self::stack::{Stack, VecStack}; use self::stack::{Stack, VecStack};
use self::memory::Memory; use self::memory::Memory;
pub use self::shared_cache::SharedCache; pub use self::shared_cache::SharedCache;
use std::marker::PhantomData;
use action_params::{ActionParams, ActionValue};
use call_type::CallType;
use instructions::{self, Instruction, InstructionInfo};
use evm::{self, GasLeft, CostType, ReturnData};
use ext::{self, MessageCallResult, ContractCreateResult, CreateContractAddress};
use bit_set::BitSet; use bit_set::BitSet;
use util::*; use util::*;
@ -107,8 +113,8 @@ pub struct Interpreter<Cost: CostType> {
_type: PhantomData<Cost>, _type: PhantomData<Cost>,
} }
impl<Cost: CostType> evm::Evm for Interpreter<Cost> { impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
fn exec(&mut self, params: ActionParams, ext: &mut ext::Ext) -> evm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
self.mem.clear(); self.mem.clear();
let mut informant = informant::EvmInformant::new(ext.depth()); let mut informant = informant::EvmInformant::new(ext.depth());
@ -205,7 +211,7 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
} }
fn verify_instruction(&self, ext: &ext::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> { fn verify_instruction(&self, ext: &vm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> vm::Result<()> {
let schedule = ext.schedule(); let schedule = ext.schedule();
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) || if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
@ -214,25 +220,25 @@ impl<Cost: CostType> Interpreter<Cost> {
((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) || ((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) ||
(instruction == instructions::REVERT && !schedule.have_revert) { (instruction == instructions::REVERT && !schedule.have_revert) {
return Err(evm::Error::BadInstruction { return Err(vm::Error::BadInstruction {
instruction: instruction instruction: instruction
}); });
} }
if info.tier == instructions::GasPriceTier::Invalid { if info.tier == instructions::GasPriceTier::Invalid {
return Err(evm::Error::BadInstruction { return Err(vm::Error::BadInstruction {
instruction: instruction instruction: instruction
}); });
} }
if !stack.has(info.args) { if !stack.has(info.args) {
Err(evm::Error::StackUnderflow { Err(vm::Error::StackUnderflow {
instruction: info.name, instruction: info.name,
wanted: info.args, wanted: info.args,
on_stack: stack.size() on_stack: stack.size()
}) })
} else if stack.size() - info.args + info.ret > schedule.stack_limit { } else if stack.size() - info.args + info.ret > schedule.stack_limit {
Err(evm::Error::OutOfStack { Err(vm::Error::OutOfStack {
instruction: info.name, instruction: info.name,
wanted: info.ret - info.args, wanted: info.ret - info.args,
limit: schedule.stack_limit limit: schedule.stack_limit
@ -272,12 +278,12 @@ impl<Cost: CostType> Interpreter<Cost> {
&mut self, &mut self,
gas: Cost, gas: Cost,
params: &ActionParams, params: &ActionParams,
ext: &mut ext::Ext, ext: &mut vm::Ext,
instruction: Instruction, instruction: Instruction,
code: &mut CodeReader, code: &mut CodeReader,
stack: &mut Stack<U256>, stack: &mut Stack<U256>,
provided: Option<Cost> provided: Option<Cost>
) -> evm::Result<InstructionResult<Cost>> { ) -> vm::Result<InstructionResult<Cost>> {
match instruction { match instruction {
instructions::JUMP => { instructions::JUMP => {
let jump = stack.pop_back(); let jump = stack.pop_back();
@ -593,13 +599,13 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
} }
fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> evm::Result<usize> { fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> vm::Result<usize> {
let jump = jump_u.low_u64() as usize; let jump = jump_u.low_u64() as usize;
if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u { if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u {
Ok(jump) Ok(jump)
} else { } else {
Err(evm::Error::BadJumpDestination { Err(vm::Error::BadJumpDestination {
destination: jump destination: jump
}) })
} }
@ -617,7 +623,7 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
} }
fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> evm::Result<()> { fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> vm::Result<()> {
match instruction { match instruction {
instructions::DUP1...instructions::DUP16 => { instructions::DUP1...instructions::DUP16 => {
let position = instructions::get_dup_position(instruction); let position = instructions::get_dup_position(instruction);
@ -822,7 +828,7 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
}, },
_ => { _ => {
return Err(evm::Error::BadInstruction { return Err(vm::Error::BadInstruction {
instruction: instruction instruction: instruction
}); });
} }

View File

@ -19,6 +19,7 @@ use util::*;
use evmjit; use evmjit;
use evm::{self, GasLeft}; use evm::{self, GasLeft};
use evm::CallType; use evm::CallType;
use vm::{self, Vm};
/// Should be used to convert jit types to ethcore /// Should be used to convert jit types to ethcore
trait FromJit<T>: Sized { trait FromJit<T>: Sized {
@ -318,7 +319,7 @@ pub struct JitEvm {
context: Option<evmjit::ContextHandle>, context: Option<evmjit::ContextHandle>,
} }
impl evm::Evm for JitEvm { impl vm::Vm for JitEvm {
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified. // Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) }; let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
@ -370,8 +371,8 @@ impl evm::Evm for JitEvm {
ext.suicide(&Address::from_jit(&context.suicide_refund_address())); ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
Ok(GasLeft::Known(U256::from(context.gas_left()))) Ok(GasLeft::Known(U256::from(context.gas_left())))
}, },
evmjit::ReturnCode::OutOfGas => Err(evm::Error::OutOfGas), evmjit::ReturnCode::OutOfGas => Err(vm::Error::OutOfGas),
_err => Err(evm::Error::Internal) _err => Err(vm::Error::Internal)
} }
} }
} }

View File

@ -24,11 +24,12 @@ extern crate ethjson;
extern crate rlp; extern crate rlp;
extern crate parity_wasm; extern crate parity_wasm;
extern crate wasm_utils; extern crate wasm_utils;
extern crate ethcore_logger;
extern crate vm;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate log; extern crate log;
#[cfg(feature = "jit")] #[cfg(feature = "jit")]
@ -37,14 +38,8 @@ extern crate evmjit;
#[cfg(test)] #[cfg(test)]
extern crate rustc_hex; extern crate rustc_hex;
pub mod action_params;
pub mod call_type;
pub mod env_info;
pub mod ext;
pub mod evm; pub mod evm;
pub mod interpreter; pub mod interpreter;
pub mod schedule;
pub mod wasm;
#[macro_use] #[macro_use]
pub mod factory; pub mod factory;
@ -59,12 +54,12 @@ mod tests;
#[cfg(all(feature="benches", test))] #[cfg(all(feature="benches", test))]
mod benches; mod benches;
pub use self::action_params::ActionParams; pub use vm::{
pub use self::call_type::CallType; Schedule, CleanDustMode, EnvInfo, CallType, ActionParams, Ext,
pub use self::env_info::EnvInfo; ContractCreateResult, MessageCallResult, CreateContractAddress,
pub use self::evm::{Evm, Error, Finalize, FinalizationResult, GasLeft, Result, CostType, ReturnData}; GasLeft, ReturnData
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress}; };
pub use self::evm::{Finalize, FinalizationResult, CostType};
pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes}; pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes};
pub use self::vmtype::VMType; pub use self::vmtype::VMType;
pub use self::factory::Factory; pub use self::factory::Factory;
pub use self::schedule::{Schedule, CleanDustMode};

View File

@ -15,212 +15,17 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt::Debug; use std::fmt::Debug;
use std::str::FromStr;
use std::hash::Hash;
use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use action_params::{ActionParams, ActionValue}; use vm::{self, ActionParams, ActionValue};
use env_info::EnvInfo; use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
use call_type::CallType;
use schedule::Schedule;
use evm::{self, GasLeft, ReturnData};
use ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
use factory::Factory; use factory::Factory;
use vmtype::VMType; use vmtype::VMType;
pub struct FakeLogEntry {
topics: Vec<H256>,
data: Bytes
}
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum FakeCallType {
Call, Create
}
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct FakeCall {
pub call_type: FakeCallType,
pub gas: U256,
pub sender_address: Option<Address>,
pub receive_address: Option<Address>,
pub value: Option<U256>,
pub data: Bytes,
pub code_address: Option<Address>,
}
/// Fake externalities test structure.
///
/// Can't do recursive calls.
#[derive(Default)]
pub struct FakeExt {
pub store: HashMap<H256, H256>,
pub suicides: HashSet<Address>,
pub calls: HashSet<FakeCall>,
sstore_clears: usize,
depth: usize,
blockhashes: HashMap<U256, H256>,
codes: HashMap<Address, Arc<Bytes>>,
logs: Vec<FakeLogEntry>,
info: EnvInfo,
schedule: Schedule,
balances: HashMap<Address, U256>,
}
// similar to the normal `finalize` function, but ignoring NeedsReturn.
fn test_finalize(res: Result<GasLeft, evm::Error>) -> Result<U256, evm::Error> {
match res {
Ok(GasLeft::Known(gas)) => Ok(gas),
Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented.
Err(e) => Err(e),
}
}
impl FakeExt {
pub fn new() -> Self {
FakeExt::default()
}
}
impl Default for Schedule {
fn default() -> Self {
Schedule::new_frontier()
}
}
impl Ext for FakeExt {
fn storage_at(&self, key: &H256) -> evm::Result<H256> {
Ok(self.store.get(key).unwrap_or(&H256::new()).clone())
}
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> {
self.store.insert(key, value);
Ok(())
}
fn exists(&self, address: &Address) -> evm::Result<bool> {
Ok(self.balances.contains_key(address))
}
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> {
Ok(self.balances.get(address).map_or(false, |b| !b.is_zero()))
}
fn origin_balance(&self) -> evm::Result<U256> {
unimplemented!()
}
fn balance(&self, address: &Address) -> evm::Result<U256> {
Ok(self.balances[address])
}
fn blockhash(&mut self, number: &U256) -> H256 {
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Create,
gas: *gas,
sender_address: None,
receive_address: None,
value: Some(*value),
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,
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Call,
gas: *gas,
sender_address: Some(sender_address.clone()),
receive_address: Some(receive_address.clone()),
value: value,
data: data.to_vec(),
code_address: Some(code_address.clone())
});
MessageCallResult::Success(*gas, ReturnData::empty())
}
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> {
Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone())
}
fn extcodesize(&self, address: &Address) -> evm::Result<usize> {
Ok(self.codes.get(address).map_or(0, |c| c.len()))
}
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> {
self.logs.push(FakeLogEntry {
topics: topics,
data: data.to_vec()
});
Ok(())
}
fn ret(self, _gas: &U256, _data: &ReturnData) -> evm::Result<U256> {
unimplemented!();
}
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> {
self.suicides.insert(refund_address.clone());
Ok(())
}
fn schedule(&self) -> &Schedule {
&self.schedule
}
fn env_info(&self) -> &EnvInfo {
&self.info
}
fn depth(&self) -> usize {
self.depth
}
fn inc_sstore_clears(&mut self) {
self.sstore_clears += 1;
}
}
#[test]
fn test_stack_underflow() {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "01600055".from_hex().unwrap();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
let mut ext = FakeExt::new();
let err = {
let mut vm : Box<evm::Evm> = Box::new(super::interpreter::Interpreter::<usize>::new(Arc::new(super::interpreter::SharedCache::default())));
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
};
match err {
evm::Error::StackUnderflow {wanted, on_stack, ..} => {
assert_eq!(wanted, 2);
assert_eq!(on_stack, 0);
}
_ => {
assert!(false, "Expected StackUndeflow")
}
};
}
evm_test!{test_add: test_add_jit, test_add_int} evm_test!{test_add: test_add_jit, test_add_int}
fn test_add(factory: super::Factory) { fn test_add(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
@ -849,7 +654,7 @@ fn test_badinstruction_int() {
}; };
match err { match err {
evm::Error::BadInstruction { instruction: 0xaf } => (), vm::Error::BadInstruction { instruction: 0xaf } => (),
_ => assert!(false, "Expected bad instruction") _ => assert!(false, "Expected bad instruction")
} }
} }

View File

@ -19,6 +19,7 @@ ethcore-io = { path = "../../util/io" }
ethcore-ipc = { path = "../../ipc/rpc", optional = true } ethcore-ipc = { path = "../../ipc/rpc", optional = true }
ethcore-devtools = { path = "../../devtools" } ethcore-devtools = { path = "../../devtools" }
evm = { path = "../evm" } evm = { path = "../evm" }
vm = { path = "../vm" }
rlp = { path = "../../util/rlp" } rlp = { path = "../../util/rlp" }
time = "0.1" time = "0.1"
smallvec = "0.4" smallvec = "0.4"

View File

@ -80,6 +80,7 @@ extern crate serde;
extern crate smallvec; extern crate smallvec;
extern crate stats; extern crate stats;
extern crate time; extern crate time;
extern crate vm;
#[cfg(feature = "ipc")] #[cfg(feature = "ipc")]
extern crate ethcore_ipc as ipc; extern crate ethcore_ipc as ipc;

View File

@ -24,7 +24,7 @@ use ethcore::engines::Engine;
use ethcore::receipt::Receipt; use ethcore::receipt::Receipt;
use ethcore::state::{self, ProvedExecution}; use ethcore::state::{self, ProvedExecution};
use ethcore::transaction::SignedTransaction; use ethcore::transaction::SignedTransaction;
use evm::env_info::EnvInfo; use vm::EnvInfo;
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field}; use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};

View File

@ -11,7 +11,6 @@
"networkID" : "0x2" "networkID" : "0x2"
}, },
"genesis": { "genesis": {
"gasLimitBoundDivisor": "0x0400",
"seal": { "seal": {
"generic": "0x" "generic": "0x"
}, },

View File

@ -3,7 +3,6 @@
"engine": { "engine": {
"basicAuthority": { "basicAuthority": {
"params": { "params": {
"gasLimitBoundDivisor": "0x0400",
"durationLimit": "0x0d", "durationLimit": "0x0d",
"validators": { "validators": {
"safeContract": "0x0000000000000000000000000000000000000005" "safeContract": "0x0000000000000000000000000000000000000005"

View File

@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! DB backend wrapper for Account trie //! DB backend wrapper for Account trie
use std::collections::HashMap;
use util::*; use util::*;
use rlp::NULL_RLP; use rlp::NULL_RLP;

View File

@ -25,7 +25,7 @@ use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RL
use util::error::{Mismatch, OutOfBounds}; use util::error::{Mismatch, OutOfBounds};
use basic_types::{LogBloom, Seal}; use basic_types::{LogBloom, Seal};
use evm::env_info::{EnvInfo, LastHashes}; use vm::{EnvInfo, LastHashes};
use engines::Engine; use engines::Engine;
use error::{Error, BlockError, TransactionError}; use error::{Error, BlockError, TransactionError};
use factory::Factories; use factory::Factories;
@ -680,7 +680,7 @@ mod tests {
use tests::helpers::*; use tests::helpers::*;
use super::*; use super::*;
use engines::Engine; use engines::Engine;
use evm::env_info::LastHashes; use vm::LastHashes;
use error::Error; use error::Error;
use header::Header; use header::Header;
use factory::Factories; use factory::Factories;

View File

@ -16,6 +16,9 @@
//! Blockchain database. //! Blockchain database.
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::mem;
use bloomchain as bc; use bloomchain as bc;
use util::*; use util::*;
use rlp::*; use rlp::*;

View File

@ -16,6 +16,8 @@
//! Blockchain DB extras. //! Blockchain DB extras.
use std::ops;
use std::io::Write;
use bloomchain; use bloomchain;
use blooms::{GroupPosition, BloomGroup}; use blooms::{GroupPosition, BloomGroup};
use db::Key; use db::Key;
@ -56,7 +58,7 @@ fn with_index(hash: &H256, i: ExtrasIndex) -> H264 {
pub struct BlockNumberKey([u8; 5]); pub struct BlockNumberKey([u8; 5]);
impl Deref for BlockNumberKey { impl ops::Deref for BlockNumberKey {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -88,7 +90,7 @@ impl Key<BlockDetails> for H256 {
pub struct LogGroupKey([u8; 6]); pub struct LogGroupKey([u8; 6]);
impl Deref for LogGroupKey { impl ops::Deref for LogGroupKey {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -160,7 +162,8 @@ pub const EPOCH_KEY_PREFIX: &'static [u8; DB_PREFIX_LEN] = &[
]; ];
pub struct EpochTransitionsKey([u8; EPOCH_KEY_LEN]); pub struct EpochTransitionsKey([u8; EPOCH_KEY_LEN]);
impl Deref for EpochTransitionsKey {
impl ops::Deref for EpochTransitionsKey {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &[u8] { &self.0[..] } fn deref(&self) -> &[u8] { &self.0[..] }

View File

@ -36,9 +36,9 @@ impl From<&'static str> for Error {
} }
} }
impl Into<::evm::Error> for Error { impl Into<::vm::Error> for Error {
fn into(self) -> ::evm::Error { fn into(self) -> ::vm::Error {
::evm::Error::BuiltIn(self.0) ::vm::Error::BuiltIn(self.0)
} }
} }

View File

@ -42,9 +42,8 @@ use client::{
}; };
use encoded; use encoded;
use engines::{Engine, EpochTransition}; use engines::{Engine, EpochTransition};
use evm::env_info::EnvInfo;
use evm::env_info::LastHashes;
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError}; use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
use vm::{EnvInfo, LastHashes};
use evm::{Factory as EvmFactory, Schedule}; use evm::{Factory as EvmFactory, Schedule};
use executive::{Executive, Executed, TransactOptions, contract_address}; use executive::{Executive, Executed, TransactOptions, contract_address};
use factory::Factories; use factory::Factories;

View File

@ -23,7 +23,7 @@ use util::kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, db, spec}; use {state, state_db, client, executive, trace, db, spec};
use factory::Factories; use factory::Factories;
use evm::{self, VMType}; use evm::{self, VMType};
use evm::action_params::ActionParams; use vm::{self, ActionParams};
/// EVM test Error. /// EVM test Error.
#[derive(Debug)] #[derive(Debug)]
@ -31,7 +31,7 @@ pub enum EvmTestError {
/// Trie integrity error. /// Trie integrity error.
Trie(util::TrieError), Trie(util::TrieError),
/// EVM error. /// EVM error.
Evm(evm::Error), Evm(vm::Error),
/// Initialization error. /// Initialization error.
Initialization(::error::Error), Initialization(::error::Error),
/// Low-level database error. /// Low-level database error.

View File

@ -40,7 +40,7 @@ pub use types::pruning_info::PruningInfo;
pub use types::call_analytics::CallAnalytics; pub use types::call_analytics::CallAnalytics;
pub use executive::{Executed, Executive, TransactOptions}; pub use executive::{Executed, Executive, TransactOptions};
pub use evm::env_info::{LastHashes, EnvInfo}; pub use vm::{LastHashes, EnvInfo};
pub use error::{BlockImportError, TransactionImportError, TransactionImportResult}; pub use error::{BlockImportError, TransactionImportError, TransactionImportResult};
pub use verification::VerifierType; pub use verification::VerifierType;

View File

@ -17,6 +17,9 @@
//! Test client. //! Test client.
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
use std::sync::Arc;
use std::collections::{HashMap, BTreeMap};
use std::mem;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use rlp::*; use rlp::*;
@ -36,7 +39,8 @@ use log_entry::LocalizedLogEntry;
use receipt::{Receipt, LocalizedReceipt}; use receipt::{Receipt, LocalizedReceipt};
use blockchain::extras::BlockReceipts; use blockchain::extras::BlockReceipts;
use error::{ImportResult, Error as EthcoreError}; use error::{ImportResult, Error as EthcoreError};
use evm::{Factory as EvmFactory, VMType, Schedule}; use evm::{Factory as EvmFactory, VMType};
use vm::Schedule;
use miner::{Miner, MinerService, TransactionImportResult}; use miner::{Miner, MinerService, TransactionImportResult};
use spec::Spec; use spec::Spec;
use types::basic_account::BasicAccount; use types::basic_account::BasicAccount;

View File

@ -19,7 +19,7 @@ use std::collections::BTreeMap;
use block::{OpenBlock, SealedBlock, ClosedBlock}; use block::{OpenBlock, SealedBlock, ClosedBlock};
use blockchain::TreeRoute; use blockchain::TreeRoute;
use encoded; use encoded;
use evm::env_info::LastHashes; use vm::LastHashes;
use error::{ImportResult, CallError, Error as EthcoreError}; use error::{ImportResult, CallError, Error as EthcoreError};
use error::{TransactionImportResult, BlockImportError}; use error::{TransactionImportResult, BlockImportError};
use evm::{Factory as EvmFactory, Schedule}; use evm::{Factory as EvmFactory, Schedule};

View File

@ -17,8 +17,10 @@
//! A blockchain engine that supports a non-instant BFT proof-of-authority. //! A blockchain engine that supports a non-instant BFT proof-of-authority.
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::Weak; use std::sync::{Weak, Arc};
use std::time::{UNIX_EPOCH, Duration}; use std::time::{UNIX_EPOCH, Duration};
use std::collections::{BTreeMap, HashSet, HashMap};
use std::cmp;
use account_provider::AccountProvider; use account_provider::AccountProvider;
use block::*; use block::*;
@ -446,9 +448,9 @@ impl Engine for AuthorityRound {
let gas_limit = parent.gas_limit().clone(); let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.params().gas_limit_bound_divisor; let bound_divisor = self.params().gas_limit_bound_divisor;
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
} else { } else {
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into())
} }
}); });
} }
@ -515,7 +517,7 @@ impl Engine for AuthorityRound {
fn on_new_block( fn on_new_block(
&self, &self,
block: &mut ExecutedBlock, block: &mut ExecutedBlock,
last_hashes: Arc<::evm::env_info::LastHashes>, last_hashes: Arc<::vm::LastHashes>,
epoch_begin: bool, epoch_begin: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let parent_hash = block.fields().header.parent_hash().clone(); let parent_hash = block.fields().header.parent_hash().clone();
@ -813,7 +815,7 @@ impl Engine for AuthorityRound {
} }
} }
fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> result::Result<(), Error> { fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> {
t.check_low_s()?; t.check_low_s()?;
if let Some(n) = t.network_id() { if let Some(n) = t.network_id() {
@ -849,6 +851,7 @@ impl Engine for AuthorityRound {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use util::*; use util::*;
use header::Header; use header::Header;
@ -939,10 +942,10 @@ mod tests {
let addr = tap.insert_account("0".sha3().into(), "0").unwrap(); let addr = tap.insert_account("0".sha3().into(), "0").unwrap();
let mut parent_header: Header = Header::default(); let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]); parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_gas_limit(U256::from_str("222222").unwrap()); parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default(); let mut header: Header = Header::default();
header.set_number(1); header.set_number(1);
header.set_gas_limit(U256::from_str("222222").unwrap()); header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_author(addr); header.set_author(addr);
let engine = Spec::new_test_round().engine; let engine = Spec::new_test_round().engine;
@ -965,10 +968,10 @@ mod tests {
let mut parent_header: Header = Header::default(); let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]); parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_gas_limit(U256::from_str("222222").unwrap()); parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default(); let mut header: Header = Header::default();
header.set_number(1); header.set_number(1);
header.set_gas_limit(U256::from_str("222222").unwrap()); header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_author(addr); header.set_author(addr);
let engine = Spec::new_test_round().engine; let engine = Spec::new_test_round().engine;
@ -991,10 +994,10 @@ mod tests {
let mut parent_header: Header = Header::default(); let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&4usize).into_vec()]); parent_header.set_seal(vec![encode(&4usize).into_vec()]);
parent_header.set_gas_limit(U256::from_str("222222").unwrap()); parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default(); let mut header: Header = Header::default();
header.set_number(1); header.set_number(1);
header.set_gas_limit(U256::from_str("222222").unwrap()); header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_author(addr); header.set_author(addr);
let engine = Spec::new_test_round().engine; let engine = Spec::new_test_round().engine;
@ -1028,10 +1031,10 @@ mod tests {
let mut parent_header: Header = Header::default(); let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&1usize).into_vec()]); parent_header.set_seal(vec![encode(&1usize).into_vec()]);
parent_header.set_gas_limit(U256::from_str("222222").unwrap()); parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default(); let mut header: Header = Header::default();
header.set_number(1); header.set_number(1);
header.set_gas_limit(U256::from_str("222222").unwrap()); header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_seal(vec![encode(&3usize).into_vec()]); header.set_seal(vec![encode(&3usize).into_vec()]);
// Do not report when signer not present. // Do not report when signer not present.

View File

@ -16,7 +16,9 @@
//! A blockchain engine that supports a basic, non-BFT proof-of-authority. //! A blockchain engine that supports a basic, non-BFT proof-of-authority.
use std::sync::Weak; use std::sync::{Weak, Arc};
use std::collections::BTreeMap;
use std::cmp;
use util::*; use util::*;
use ethkey::{recover, public_to_address, Signature}; use ethkey::{recover, public_to_address, Signature};
use account_provider::AccountProvider; use account_provider::AccountProvider;
@ -116,9 +118,9 @@ impl Engine for BasicAuthority {
let gas_limit = parent.gas_limit().clone(); let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.params().gas_limit_bound_divisor; let bound_divisor = self.params().gas_limit_bound_divisor;
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
} else { } else {
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into())
} }
}); });
} }
@ -142,7 +144,7 @@ impl Engine for BasicAuthority {
Seal::None Seal::None
} }
fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// check the seal fields. // check the seal fields.
// TODO: pull this out into common code. // TODO: pull this out into common code.
if header.seal().len() != self.seal_fields() { if header.seal().len() != self.seal_fields() {
@ -153,11 +155,11 @@ impl Engine for BasicAuthority {
Ok(()) Ok(())
} }
fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
Ok(()) Ok(())
} }
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// Do not calculate difficulty for genesis blocks. // Do not calculate difficulty for genesis blocks.
if header.number() == 0 { if header.number() == 0 {
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
@ -249,6 +251,7 @@ impl Engine for BasicAuthority {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use util::*; use util::*;
use block::*; use block::*;
use error::{BlockError, Error}; use error::{BlockError, Error};

View File

@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashMap};
use util::{Address, HashMap}; use util::Address;
use builtin::Builtin; use builtin::Builtin;
use engines::{Engine, Seal}; use engines::{Engine, Seal};
use spec::CommonParams; use spec::CommonParams;
@ -63,6 +63,7 @@ impl Engine for InstantSeal {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use util::*; use util::*;
use tests::helpers::*; use tests::helpers::*;
use spec::Spec; use spec::Spec;

View File

@ -35,7 +35,9 @@ pub use self::instant_seal::InstantSeal;
pub use self::null_engine::NullEngine; pub use self::null_engine::NullEngine;
pub use self::tendermint::Tendermint; pub use self::tendermint::Tendermint;
use std::sync::Weak; use std::sync::{Weak, Arc};
use std::collections::{BTreeMap, HashMap};
use std::fmt;
use self::epoch::PendingTransition; use self::epoch::PendingTransition;
@ -43,16 +45,14 @@ use account_provider::AccountProvider;
use block::ExecutedBlock; use block::ExecutedBlock;
use builtin::Builtin; use builtin::Builtin;
use client::Client; use client::Client;
use evm::env_info::{EnvInfo, LastHashes}; use vm::{EnvInfo, LastHashes, Schedule, CreateContractAddress};
use error::Error; use error::Error;
use evm::Schedule;
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};
use receipt::Receipt; use receipt::Receipt;
use trace::FlatTrace; use trace::FlatTrace;
use snapshot::SnapshotComponents; use snapshot::SnapshotComponents;
use spec::CommonParams; use spec::CommonParams;
use transaction::{UnverifiedTransaction, SignedTransaction}; use transaction::{UnverifiedTransaction, SignedTransaction};
use evm::CreateContractAddress;
use ethkey::Signature; use ethkey::Signature;
use util::*; use util::*;
@ -401,13 +401,12 @@ pub trait Engine : Sync + Send {
/// Common engine utilities /// Common engine utilities
pub mod common { pub mod common {
use std::sync::Arc;
use block::ExecutedBlock; use block::ExecutedBlock;
use evm::env_info::{EnvInfo, LastHashes};
use error::Error; use error::Error;
use transaction::SYSTEM_ADDRESS; use transaction::SYSTEM_ADDRESS;
use executive::Executive; use executive::Executive;
use evm::CallType; use vm::{CallType, ActionParams, ActionValue, EnvInfo, LastHashes};
use evm::action_params::{ActionParams, ActionValue};
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use state::Substate; use state::Substate;

View File

@ -16,7 +16,8 @@
//! A signer used by Engines which need to sign messages. //! A signer used by Engines which need to sign messages.
use util::{Arc, H256, Address}; use std::sync::Arc;
use util::{H256, Address};
use ethkey::Signature; use ethkey::Signature;
use account_provider::{self, AccountProvider}; use account_provider::{self, AccountProvider};

View File

@ -16,6 +16,7 @@
//! Tendermint message handling. //! Tendermint message handling.
use std::cmp;
use util::*; use util::*;
use super::{Height, View, BlockHash, Step}; use super::{Height, View, BlockHash, Step};
use error::Error; use error::Error;
@ -110,13 +111,13 @@ impl Default for VoteStep {
} }
impl PartialOrd for VoteStep { impl PartialOrd for VoteStep {
fn partial_cmp(&self, m: &VoteStep) -> Option<Ordering> { fn partial_cmp(&self, m: &VoteStep) -> Option<cmp::Ordering> {
Some(self.cmp(m)) Some(self.cmp(m))
} }
} }
impl Ord for VoteStep { impl Ord for VoteStep {
fn cmp(&self, m: &VoteStep) -> Ordering { fn cmp(&self, m: &VoteStep) -> cmp::Ordering {
if self.height != m.height { if self.height != m.height {
self.height.cmp(&m.height) self.height.cmp(&m.height)
} else if self.view != m.view { } else if self.view != m.view {
@ -198,6 +199,7 @@ pub fn message_hash(vote_step: VoteStep, block_hash: H256) -> H256 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use util::*; use util::*;
use rlp::*; use rlp::*;
use account_provider::AccountProvider; use account_provider::AccountProvider;

View File

@ -25,8 +25,10 @@
mod message; mod message;
mod params; mod params;
use std::sync::Weak; use std::sync::{Weak, Arc};
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use std::collections::{HashSet, BTreeMap, HashMap};
use std::cmp;
use util::*; use util::*;
use client::{Client, EngineClient}; use client::{Client, EngineClient};
use error::{Error, BlockError}; use error::{Error, BlockError};
@ -470,9 +472,9 @@ impl Engine for Tendermint {
let gas_limit = parent.gas_limit().clone(); let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.params().gas_limit_bound_divisor; let bound_divisor = self.params().gas_limit_bound_divisor;
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
} else { } else {
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into())
} }
}); });
} }
@ -783,6 +785,7 @@ impl Engine for Tendermint {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::FromStr;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use block::*; use block::*;

View File

@ -126,6 +126,7 @@ impl ValidatorSet for ValidatorContract {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use rlp::encode; use rlp::encode;
@ -142,11 +143,11 @@ mod tests {
#[test] #[test]
fn fetches_validators() { fn fetches_validators() {
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None);
let vc = Arc::new(ValidatorContract::new(Address::from_str("0000000000000000000000000000000000000005").unwrap())); let vc = Arc::new(ValidatorContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
vc.register_contract(Arc::downgrade(&client)); vc.register_contract(Arc::downgrade(&client));
let last_hash = client.best_block_header().hash(); let last_hash = client.best_block_header().hash();
assert!(vc.contains(&last_hash, &Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap())); assert!(vc.contains(&last_hash, &"7d577a597b2742b498cb5cf0c26cdcd726d39e6e".parse::<Address>().unwrap()));
assert!(vc.contains(&last_hash, &Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap())); assert!(vc.contains(&last_hash, &"82a978b3f5962a5b0957d9ee9eef472ee55b42f1".parse::<Address>().unwrap()));
} }
#[test] #[test]
@ -155,7 +156,7 @@ mod tests {
let v1 = tap.insert_account("1".sha3().into(), "").unwrap(); let v1 = tap.insert_account("1".sha3().into(), "").unwrap();
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone())); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone()));
client.engine().register_client(Arc::downgrade(&client)); client.engine().register_client(Arc::downgrade(&client));
let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap(); let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
// Make sure reporting can be done. // Make sure reporting can be done.
client.miner().set_gas_floor_target(1_000_000.into()); client.miner().set_gas_floor_target(1_000_000.into());

View File

@ -142,6 +142,8 @@ impl ValidatorSet for Multi {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use std::collections::BTreeMap;
use account_provider::AccountProvider; use account_provider::AccountProvider;
use client::{BlockChainClient, EngineClient}; use client::{BlockChainClient, EngineClient};
use engines::EpochChange; use engines::EpochChange;

View File

@ -16,7 +16,7 @@
/// Validator set maintained in a contract, updated using `getValidators` method. /// Validator set maintained in a contract, updated using `getValidators` method.
use std::sync::Weak; use std::sync::{Weak, Arc};
use futures::Future; use futures::Future;
use native_contracts::ValidatorSet as Provider; use native_contracts::ValidatorSet as Provider;
@ -299,7 +299,7 @@ impl ValidatorSet for ValidatorSafeContract {
let (old_header, state_items) = decode_first_proof(&rlp)?; let (old_header, state_items) = decode_first_proof(&rlp)?;
let old_hash = old_header.hash(); let old_hash = old_header.hash();
let env_info = ::evm::env_info::EnvInfo { let env_info = ::vm::EnvInfo {
number: old_header.number(), number: old_header.number(),
author: *old_header.author(), author: *old_header.author(),
difficulty: *old_header.difficulty(), difficulty: *old_header.difficulty(),
@ -422,6 +422,7 @@ impl ValidatorSet for ValidatorSafeContract {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use types::ids::BlockId; use types::ids::BlockId;
@ -438,11 +439,11 @@ mod tests {
#[test] #[test]
fn fetches_validators() { fn fetches_validators() {
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
let vc = Arc::new(ValidatorSafeContract::new(Address::from_str("0000000000000000000000000000000000000005").unwrap())); let vc = Arc::new(ValidatorSafeContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
vc.register_contract(Arc::downgrade(&client)); vc.register_contract(Arc::downgrade(&client));
let last_hash = client.best_block_header().hash(); let last_hash = client.best_block_header().hash();
assert!(vc.contains(&last_hash, &Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap())); assert!(vc.contains(&last_hash, &"7d577a597b2742b498cb5cf0c26cdcd726d39e6e".parse::<Address>().unwrap()));
assert!(vc.contains(&last_hash, &Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap())); assert!(vc.contains(&last_hash, &"82a978b3f5962a5b0957d9ee9eef472ee55b42f1".parse::<Address>().unwrap()));
} }
#[test] #[test]
@ -454,7 +455,7 @@ mod tests {
let network_id = Spec::new_validator_safe_contract().network_id(); let network_id = Spec::new_validator_safe_contract().network_id();
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap)); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
client.engine().register_client(Arc::downgrade(&client)); client.engine().register_client(Arc::downgrade(&client));
let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap(); let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
client.miner().set_engine_signer(v1, "".into()).unwrap(); client.miner().set_engine_signer(v1, "".into()).unwrap();
// Remove "1" validator. // Remove "1" validator.
@ -520,7 +521,7 @@ mod tests {
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
let engine = client.engine().clone(); let engine = client.engine().clone();
let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap(); let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
let last_hash = client.best_block_header().hash(); let last_hash = client.best_block_header().hash();
let mut new_header = Header::default(); let mut new_header = Header::default();

View File

@ -17,8 +17,9 @@
/// Used for Engine testing. /// Used for Engine testing.
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use util::{Arc, Bytes, H256, Address, HeapSizeOf}; use util::{Bytes, H256, Address, HeapSizeOf};
use engines::{Call, Engine}; use engines::{Call, Engine};
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};

View File

@ -17,6 +17,8 @@
//! Collects votes on hashes at each Message::Round. //! Collects votes on hashes at each Message::Round.
use std::fmt::Debug; use std::fmt::Debug;
use std::collections::{BTreeMap, HashSet, HashMap};
use std::hash::Hash;
use util::*; use util::*;
use rlp::{Encodable, RlpStream}; use rlp::{Encodable, RlpStream};

View File

@ -16,6 +16,7 @@
//! General error types for use in ethcore. //! General error types for use in ethcore.
use std::fmt;
use util::*; use util::*;
use io::*; use io::*;
use header::BlockNumber; use header::BlockNumber;

View File

@ -15,11 +15,14 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::path::Path; use std::path::Path;
use std::cmp;
use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;
use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager}; use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager};
use util::*; use util::*;
use block::*; use block::*;
use builtin::Builtin; use builtin::Builtin;
use evm::env_info::EnvInfo; use vm::EnvInfo;
use error::{BlockError, Error, TransactionError}; use error::{BlockError, Error, TransactionError};
use trace::{Tracer, ExecutiveTracer,RewardType}; use trace::{Tracer, ExecutiveTracer,RewardType};
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};
@ -30,7 +33,7 @@ use engines::{self, Engine, CloseOutcome};
use evm::Schedule; use evm::Schedule;
use ethjson; use ethjson;
use rlp::{self, UntrustedRlp}; use rlp::{self, UntrustedRlp};
use evm::env_info::LastHashes; use vm::LastHashes;
/// Parity tries to round block.gas_limit to multiple of this constant /// Parity tries to round block.gas_limit to multiple of this constant
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
@ -224,15 +227,15 @@ impl Engine for Arc<Ethash> {
let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into();
let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into();
let gas_limit = if gas_limit < gas_floor_target { let gas_limit = if gas_limit < gas_floor_target {
let gas_limit = min(gas_floor_target, upper_limit); let gas_limit = cmp::min(gas_floor_target, upper_limit);
round_block_gas_limit(gas_limit, lower_limit, upper_limit) round_block_gas_limit(gas_limit, lower_limit, upper_limit)
} else if gas_limit > gas_ceil_target { } else if gas_limit > gas_ceil_target {
let gas_limit = max(gas_ceil_target, lower_limit); let gas_limit = cmp::max(gas_ceil_target, lower_limit);
round_block_gas_limit(gas_limit, lower_limit, upper_limit) round_block_gas_limit(gas_limit, lower_limit, upper_limit)
} else { } else {
let total_lower_limit = max(lower_limit, gas_floor_target); let total_lower_limit = cmp::max(lower_limit, gas_floor_target);
let total_upper_limit = min(upper_limit, gas_ceil_target); let total_upper_limit = cmp::min(upper_limit, gas_ceil_target);
let gas_limit = max(gas_floor_target, min(total_upper_limit, let gas_limit = cmp::max(gas_floor_target, cmp::min(total_upper_limit,
lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor));
round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit)
}; };
@ -329,7 +332,7 @@ impl Engine for Arc<Ethash> {
} }
} }
fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// check the seal fields. // check the seal fields.
if header.seal().len() != self.seal_fields() { if header.seal().len() != self.seal_fields() {
return Err(From::from(BlockError::InvalidSealArity( return Err(From::from(BlockError::InvalidSealArity(
@ -367,7 +370,7 @@ impl Engine for Arc<Ethash> {
Ok(()) Ok(())
} }
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
if header.seal().len() != self.seal_fields() { if header.seal().len() != self.seal_fields() {
return Err(From::from(BlockError::InvalidSealArity( return Err(From::from(BlockError::InvalidSealArity(
Mismatch { expected: self.seal_fields(), found: header.seal().len() } Mismatch { expected: self.seal_fields(), found: header.seal().len() }
@ -386,7 +389,7 @@ impl Engine for Arc<Ethash> {
Ok(()) Ok(())
} }
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// we should not calculate difficulty for genesis blocks // we should not calculate difficulty for genesis blocks
if header.number() == 0 { if header.number() == 0 {
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
@ -410,7 +413,7 @@ impl Engine for Arc<Ethash> {
Ok(()) Ok(())
} }
fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> result::Result<(), Error> { fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> {
if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price { if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price {
return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into()); return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into());
} }
@ -503,28 +506,28 @@ impl Ethash {
if diff_inc <= threshold { if diff_inc <= threshold {
*parent.difficulty() + *parent.difficulty() / difficulty_bound_divisor * (threshold - diff_inc).into() *parent.difficulty() + *parent.difficulty() / difficulty_bound_divisor * (threshold - diff_inc).into()
} else { } else {
let multiplier = min(diff_inc - threshold, 99).into(); let multiplier = cmp::min(diff_inc - threshold, 99).into();
parent.difficulty().saturating_sub( parent.difficulty().saturating_sub(
*parent.difficulty() / difficulty_bound_divisor * multiplier *parent.difficulty() / difficulty_bound_divisor * multiplier
) )
} }
}; };
target = max(min_difficulty, target); target = cmp::max(min_difficulty, target);
if header.number() < self.ethash_params.bomb_defuse_transition { if header.number() < self.ethash_params.bomb_defuse_transition {
if header.number() < self.ethash_params.ecip1010_pause_transition { if header.number() < self.ethash_params.ecip1010_pause_transition {
let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize;
if period > 1 { if period > 1 {
target = max(min_difficulty, target + (U256::from(1) << (period - 2))); target = cmp::max(min_difficulty, target + (U256::from(1) << (period - 2)));
} }
} }
else if header.number() < self.ethash_params.ecip1010_continue_transition { else if header.number() < self.ethash_params.ecip1010_continue_transition {
let fixed_difficulty = ((self.ethash_params.ecip1010_pause_transition / EXP_DIFF_PERIOD) - 2) as usize; let fixed_difficulty = ((self.ethash_params.ecip1010_pause_transition / EXP_DIFF_PERIOD) - 2) as usize;
target = max(min_difficulty, target + (U256::from(1) << fixed_difficulty)); target = cmp::max(min_difficulty, target + (U256::from(1) << fixed_difficulty));
} }
else { else {
let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize;
let delay = ((self.ethash_params.ecip1010_continue_transition - self.ethash_params.ecip1010_pause_transition) / EXP_DIFF_PERIOD) as usize; let delay = ((self.ethash_params.ecip1010_continue_transition - self.ethash_params.ecip1010_pause_transition) / EXP_DIFF_PERIOD) as usize;
target = max(min_difficulty, target + (U256::from(1) << (period - delay - 2))); target = cmp::max(min_difficulty, target + (U256::from(1) << (period - delay - 2)));
} }
} }
target target
@ -569,6 +572,9 @@ impl Header {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::FromStr;
use std::collections::BTreeMap;
use std::sync::Arc;
use util::*; use util::*;
use block::*; use block::*;
use tests::helpers::*; use tests::helpers::*;

View File

@ -134,23 +134,4 @@ mod tests {
let _ = frontier.engine; let _ = frontier.engine;
} }
#[test]
fn all_spec_files_valid() {
let tmp = ::std::env::temp_dir();
new_olympic(&tmp);
new_foundation(&tmp);
new_classic(&tmp);
new_expanse(&tmp);
new_kovan(&tmp);
new_ropsten(&tmp);
new_morden(&tmp);
new_frontier_test();
new_homestead_test();
new_eip150_test();
new_eip161_test();
new_transition_test();
new_mainnet_like();
new_metropolis_test();
}
} }

View File

@ -17,7 +17,7 @@
//! Transaction execution format module. //! Transaction execution format module.
use util::{Bytes, U256, Address, U512, trie}; use util::{Bytes, U256, Address, U512, trie};
use evm; use vm;
use trace::{VMTrace, FlatTrace}; use trace::{VMTrace, FlatTrace};
use log_entry::LogEntry; use log_entry::LogEntry;
use state_diff::StateDiff; use state_diff::StateDiff;
@ -28,7 +28,7 @@ use std::fmt;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Executed { pub struct Executed {
/// True if the outer call/create resulted in an exceptional exit. /// True if the outer call/create resulted in an exceptional exit.
pub exception: Option<evm::Error>, pub exception: Option<vm::Error>,
/// Gas paid up front for execution of transaction. /// Gas paid up front for execution of transaction.
pub gas: U256, pub gas: U256,

View File

@ -15,14 +15,16 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Transaction Execution environment. //! Transaction Execution environment.
use std::cmp;
use std::sync::Arc;
use util::*; use util::*;
use evm::action_params::{ActionParams, ActionValue};
use state::{Backend as StateBackend, State, Substate, CleanupMode}; use state::{Backend as StateBackend, State, Substate, CleanupMode};
use engines::Engine; use engines::Engine;
use evm::CallType; use vm::EnvInfo;
use evm::env_info::EnvInfo;
use error::ExecutionError; use error::ExecutionError;
use evm::{self, wasm, Factory, Ext, Finalize, CreateContractAddress, FinalizationResult, ReturnData, CleanDustMode}; use evm::{CallType, Factory, Finalize, FinalizationResult};
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue};
use wasm;
use externalities::*; use externalities::*;
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer}; use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
use transaction::{Action, SignedTransaction}; use transaction::{Action, SignedTransaction};
@ -75,7 +77,7 @@ pub struct TransactOptions {
} }
pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams) pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams)
-> Box<evm::Evm> where E: Engine + ?Sized -> Box<vm::Vm> where E: Engine + ?Sized
{ {
if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) { if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new( Box::new(
@ -269,7 +271,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
output_policy: OutputPolicy, output_policy: OutputPolicy,
tracer: &mut T, tracer: &mut T,
vm_tracer: &mut V vm_tracer: &mut V
) -> evm::Result<FinalizationResult> where T: Tracer, V: VMTracer { ) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH); let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH);
let static_call = params.call_type == CallType::StaticCall; let static_call = params.call_type == CallType::StaticCall;
@ -299,7 +301,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
/// Calls contract function with given contract params. /// Calls contract function with given contract params.
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides). /// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate and the output. /// Modifies the substate and the output.
/// Returns either gas_left or `evm::Error`. /// Returns either gas_left or `vm::Error`.
pub fn call<T, V>( pub fn call<T, V>(
&mut self, &mut self,
params: ActionParams, params: ActionParams,
@ -307,14 +309,14 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
mut output: BytesRef, mut output: BytesRef,
tracer: &mut T, tracer: &mut T,
vm_tracer: &mut V vm_tracer: &mut V
) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
if (params.call_type == CallType::StaticCall || if (params.call_type == CallType::StaticCall ||
((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) && ((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) &&
self.static_flag)) self.static_flag))
&& params.value.value() > 0.into() { && params.value.value() > 0.into() {
return Err(evm::Error::MutableCallInStaticContext); return Err(vm::Error::MutableCallInStaticContext);
} }
// backup used in case of running out of gas // backup used in case of running out of gas
@ -344,7 +346,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
if cost <= params.gas { if cost <= params.gas {
if let Err(e) = builtin.execute(data, &mut output) { if let Err(e) = builtin.execute(data, &mut output) {
self.state.revert_to_checkpoint(); self.state.revert_to_checkpoint();
let evm_err: evm::evm::Error = e.into(); let evm_err: vm::Error = e.into();
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into()); tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
Err(evm_err) Err(evm_err)
} else { } else {
@ -371,9 +373,9 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
// just drain the whole gas // just drain the whole gas
self.state.revert_to_checkpoint(); self.state.revert_to_checkpoint();
tracer.trace_failed_call(trace_info, vec![], evm::Error::OutOfGas.into()); tracer.trace_failed_call(trace_info, vec![], vm::Error::OutOfGas.into());
Err(evm::Error::OutOfGas) Err(vm::Error::OutOfGas)
} }
} else { } else {
let trace_info = tracer.prepare_trace_call(&params); let trace_info = tracer.prepare_trace_call(&params);
@ -432,17 +434,17 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
substate: &mut Substate, substate: &mut Substate,
tracer: &mut T, tracer: &mut T,
vm_tracer: &mut V, vm_tracer: &mut V,
) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
let scheme = self.engine.create_address_scheme(self.info.number); let scheme = self.engine.create_address_scheme(self.info.number);
if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(&params.address)? { if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(&params.address)? {
return Err(evm::Error::OutOfGas); return Err(vm::Error::OutOfGas);
} }
if params.call_type == CallType::StaticCall || self.static_flag { if params.call_type == CallType::StaticCall || self.static_flag {
let trace_info = tracer.prepare_trace_create(&params); let trace_info = tracer.prepare_trace_create(&params);
tracer.trace_failed_create(trace_info, vec![], evm::Error::MutableCallInStaticContext.into()); tracer.trace_failed_create(trace_info, vec![], vm::Error::MutableCallInStaticContext.into());
return Err(evm::Error::MutableCallInStaticContext); return Err(vm::Error::MutableCallInStaticContext);
} }
// backup used in case of running out of gas // backup used in case of running out of gas
@ -496,7 +498,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
&mut self, &mut self,
t: &SignedTransaction, t: &SignedTransaction,
mut substate: Substate, mut substate: Substate,
result: evm::Result<(U256, ReturnData)>, result: vm::Result<(U256, ReturnData)>,
output: Bytes, output: Bytes,
trace: Vec<FlatTrace>, trace: Vec<FlatTrace>,
vm_trace: Option<VMTrace> vm_trace: Option<VMTrace>
@ -538,7 +540,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?; self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?;
match result { match result {
Err(evm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)), Err(vm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)),
Err(exception) => { Err(exception) => {
Ok(Executed { Ok(Executed {
exception: Some(exception), exception: Some(exception),
@ -572,20 +574,20 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
} }
} }
fn enact_result(&mut self, result: &evm::Result<FinalizationResult>, substate: &mut Substate, un_substate: Substate) { fn enact_result(&mut self, result: &vm::Result<FinalizationResult>, substate: &mut Substate, un_substate: Substate) {
match *result { match *result {
Err(evm::Error::OutOfGas) Err(vm::Error::OutOfGas)
| Err(evm::Error::BadJumpDestination {..}) | Err(vm::Error::BadJumpDestination {..})
| Err(evm::Error::BadInstruction {.. }) | Err(vm::Error::BadInstruction {.. })
| Err(evm::Error::StackUnderflow {..}) | Err(vm::Error::StackUnderflow {..})
| Err(evm::Error::BuiltIn {..}) | Err(vm::Error::BuiltIn {..})
| Err(evm::Error::Wasm {..}) | Err(vm::Error::Wasm {..})
| Err(evm::Error::OutOfStack {..}) | Err(vm::Error::OutOfStack {..})
| Err(evm::Error::MutableCallInStaticContext) | Err(vm::Error::MutableCallInStaticContext)
| Ok(FinalizationResult { apply_state: false, .. }) => { | Ok(FinalizationResult { apply_state: false, .. }) => {
self.state.revert_to_checkpoint(); self.state.revert_to_checkpoint();
}, },
Ok(_) | Err(evm::Error::Internal(_)) => { Ok(_) | Err(vm::Error::Internal(_)) => {
self.state.discard_checkpoint(); self.state.discard_checkpoint();
substate.accrue(un_substate); substate.accrue(un_substate);
} }
@ -597,14 +599,14 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
#[allow(dead_code)] #[allow(dead_code)]
mod tests { mod tests {
use std::sync::Arc; use std::sync::Arc;
use std::str::FromStr;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use super::*; use super::*;
use util::{H256, U256, U512, Address, FromStr}; use util::{H256, U256, U512, Address};
use util::bytes::BytesRef; use util::bytes::BytesRef;
use evm::action_params::{ActionParams, ActionValue}; use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
use evm::env_info::EnvInfo; use evm::{Factory, VMType};
use evm::{Factory, VMType, CreateContractAddress};
use error::ExecutionError; use error::ExecutionError;
use state::{Substate, CleanupMode}; use state::{Substate, CleanupMode};
use tests::helpers::*; use tests::helpers::*;
@ -613,8 +615,6 @@ mod tests {
use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer}; use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer};
use transaction::{Action, Transaction}; use transaction::{Action, Transaction};
use evm::CallType;
#[test] #[test]
fn test_contract_address() { fn test_contract_address() {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();

View File

@ -15,14 +15,17 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Transaction Execution environment. //! Transaction Execution environment.
use std::cmp;
use std::sync::Arc;
use util::*; use util::*;
use evm::action_params::{ActionParams, ActionValue};
use state::{Backend as StateBackend, State, Substate, CleanupMode}; use state::{Backend as StateBackend, State, Substate, CleanupMode};
use engines::Engine; use engines::Engine;
use evm::env_info::EnvInfo;
use executive::*; use executive::*;
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData}; use vm::{
use evm::CallType; self, ActionParams, ActionValue, EnvInfo, CallType, Schedule,
Ext, ContractCreateResult, MessageCallResult, CreateContractAddress,
ReturnData
};
use transaction::UNSIGNED_SENDER; use transaction::UNSIGNED_SENDER;
use trace::{Tracer, VMTracer}; use trace::{Tracer, VMTracer};
@ -109,31 +112,31 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E>
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
{ {
fn storage_at(&self, key: &H256) -> evm::Result<H256> { fn storage_at(&self, key: &H256) -> vm::Result<H256> {
self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) self.state.storage_at(&self.origin_info.address, key).map_err(Into::into)
} }
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> { fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
if self.static_flag { if self.static_flag {
Err(evm::Error::MutableCallInStaticContext) Err(vm::Error::MutableCallInStaticContext)
} else { } else {
self.state.set_storage(&self.origin_info.address, key, value).map_err(Into::into) self.state.set_storage(&self.origin_info.address, key, value).map_err(Into::into)
} }
} }
fn exists(&self, address: &Address) -> evm::Result<bool> { fn exists(&self, address: &Address) -> vm::Result<bool> {
self.state.exists(address).map_err(Into::into) self.state.exists(address).map_err(Into::into)
} }
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> { fn exists_and_not_null(&self, address: &Address) -> vm::Result<bool> {
self.state.exists_and_not_null(address).map_err(Into::into) self.state.exists_and_not_null(address).map_err(Into::into)
} }
fn origin_balance(&self) -> evm::Result<U256> { fn origin_balance(&self) -> vm::Result<U256> {
self.balance(&self.origin_info.address).map_err(Into::into) self.balance(&self.origin_info.address).map_err(Into::into)
} }
fn balance(&self, address: &Address) -> evm::Result<U256> { fn balance(&self, address: &Address) -> vm::Result<U256> {
self.state.balance(address).map_err(Into::into) self.state.balance(address).map_err(Into::into)
} }
@ -274,16 +277,16 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
} }
} }
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> { fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![]))) Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![])))
} }
fn extcodesize(&self, address: &Address) -> evm::Result<usize> { fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
Ok(self.state.code_size(address)?.unwrap_or(0)) Ok(self.state.code_size(address)?.unwrap_or(0))
} }
#[cfg_attr(feature="dev", allow(match_ref_pats))] #[cfg_attr(feature="dev", allow(match_ref_pats))]
fn ret(mut self, gas: &U256, data: &ReturnData) -> evm::Result<U256> fn ret(mut self, gas: &U256, data: &ReturnData) -> vm::Result<U256>
where Self: Sized { where Self: Sized {
let handle_copy = |to: &mut Option<&mut Bytes>| { let handle_copy = |to: &mut Option<&mut Bytes>| {
to.as_mut().map(|b| **b = data.to_vec()); to.as_mut().map(|b| **b = data.to_vec());
@ -307,7 +310,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas); let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
if return_cost > *gas || data.len() > self.schedule.create_data_limit { if return_cost > *gas || data.len() > self.schedule.create_data_limit {
return match self.schedule.exceptional_failed_code_deposit { return match self.schedule.exceptional_failed_code_deposit {
true => Err(evm::Error::OutOfGas), true => Err(vm::Error::OutOfGas),
false => Ok(*gas) false => Ok(*gas)
} }
} }
@ -320,11 +323,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
} }
} }
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> { fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
use log_entry::LogEntry; use log_entry::LogEntry;
if self.static_flag { if self.static_flag {
return Err(evm::Error::MutableCallInStaticContext); return Err(vm::Error::MutableCallInStaticContext);
} }
let address = self.origin_info.address.clone(); let address = self.origin_info.address.clone();
@ -337,9 +340,9 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
Ok(()) Ok(())
} }
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> { fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> {
if self.static_flag { if self.static_flag {
return Err(evm::Error::MutableCallInStaticContext); return Err(vm::Error::MutableCallInStaticContext);
} }
let address = self.origin_info.address.clone(); let address = self.origin_info.address.clone();
@ -396,13 +399,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
mod tests { mod tests {
use util::*; use util::*;
use engines::Engine; use engines::Engine;
use evm::env_info::EnvInfo; use evm::{EnvInfo, Ext, CallType};
use evm::Ext;
use state::{State, Substate}; use state::{State, Substate};
use tests::helpers::*; use tests::helpers::*;
use super::*; use super::*;
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use evm::CallType;
fn get_test_origin() -> OriginInfo { fn get_test_origin() -> OriginInfo {
OriginInfo { OriginInfo {
@ -470,7 +471,7 @@ mod tests {
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
assert_eq!(hash, H256::zero()); assert_eq!(hash, H256::zero());
} }
@ -494,7 +495,7 @@ mod tests {
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
assert_eq!(test_hash, hash); assert_eq!(test_hash, hash);
} }
@ -513,10 +514,10 @@ mod tests {
// this should panic because we have no balance on any account // this should panic because we have no balance on any account
ext.call( ext.call(
&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap(), &"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap(),
&Address::new(), &Address::new(),
&Address::new(), &Address::new(),
Some(U256::from_str("0000000000000000000000000000000000000000000000000000000000150000").unwrap()), Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
&[], &[],
&Address::new(), &Address::new(),
&mut output, &mut output,

View File

@ -16,13 +16,13 @@
//! Block header. //! Block header.
use std::cmp;
use std::cell::RefCell;
use util::*; use util::*;
use basic_types::{LogBloom, ZERO_LOGBLOOM}; use basic_types::{LogBloom, ZERO_LOGBLOOM};
use time::get_time; use time::get_time;
use rlp::*; use rlp::*;
use std::cell::RefCell;
pub use basic_types::Seal; pub use basic_types::Seal;
pub use types::BlockNumber; pub use types::BlockNumber;
@ -175,7 +175,7 @@ impl Header {
/// Set the timestamp field of the header. /// Set the timestamp field of the header.
pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); } pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); }
/// Set the timestamp field of the header to the current time. /// Set the timestamp field of the header to the current time.
pub fn set_timestamp_now(&mut self, but_later_than: u64) { self.timestamp = max(get_time().sec as u64, but_later_than + 1); self.note_dirty(); } pub fn set_timestamp_now(&mut self, but_later_than: u64) { self.timestamp = cmp::max(get_time().sec as u64, but_later_than + 1); self.note_dirty(); }
/// Set the number field of the header. /// Set the number field of the header.
pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); } pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); }
/// Set the author field of the header. /// Set the author field of the header.
@ -275,7 +275,7 @@ impl Decodable for Header {
number: r.val_at(8)?, number: r.val_at(8)?,
gas_limit: r.val_at(9)?, gas_limit: r.val_at(9)?,
gas_used: r.val_at(10)?, gas_used: r.val_at(10)?,
timestamp: min(r.val_at::<U256>(11)?, u64::max_value().into()).as_u64(), timestamp: cmp::min(r.val_at::<U256>(11)?, u64::max_value().into()).as_u64(),
extra_data: r.val_at(12)?, extra_data: r.val_at(12)?,
seal: vec![], seal: vec![],
hash: RefCell::new(Some(r.as_raw().sha3())), hash: RefCell::new(Some(r.as_raw().sha3())),

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use super::test_common::*; use std::sync::Arc;
use client::{BlockChainClient, Client, ClientConfig}; use client::{BlockChainClient, Client, ClientConfig};
use block::Block; use block::Block;
use ethereum; use ethereum;

View File

@ -14,16 +14,18 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use super::test_common::*; use super::test_common::*;
use evm::action_params::ActionParams;
use state::{Backend as StateBackend, State, Substate}; use state::{Backend as StateBackend, State, Substate};
use executive::*; use executive::*;
use engines::Engine; use engines::Engine;
use evm::env_info::EnvInfo; use evm::{VMType, Finalize};
use evm; use vm::{
use evm::{Schedule, Ext, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData}; self, ActionParams, CallType, Schedule, Ext,
ContractCreateResult, EnvInfo, MessageCallResult,
CreateContractAddress, ReturnData,
};
use externalities::*; use externalities::*;
use evm::CallType;
use tests::helpers::*; use tests::helpers::*;
use ethjson; use ethjson;
use trace::{Tracer, NoopTracer}; use trace::{Tracer, NoopTracer};
@ -88,27 +90,27 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E>
impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized
{ {
fn storage_at(&self, key: &H256) -> evm::Result<H256> { fn storage_at(&self, key: &H256) -> vm::Result<H256> {
self.ext.storage_at(key) self.ext.storage_at(key)
} }
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> { fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
self.ext.set_storage(key, value) self.ext.set_storage(key, value)
} }
fn exists(&self, address: &Address) -> evm::Result<bool> { fn exists(&self, address: &Address) -> vm::Result<bool> {
self.ext.exists(address) self.ext.exists(address)
} }
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool> { fn exists_and_not_null(&self, address: &Address) -> vm::Result<bool> {
self.ext.exists_and_not_null(address) self.ext.exists_and_not_null(address)
} }
fn balance(&self, address: &Address) -> evm::Result<U256> { fn balance(&self, address: &Address) -> vm::Result<U256> {
self.ext.balance(address) self.ext.balance(address)
} }
fn origin_balance(&self) -> evm::Result<U256> { fn origin_balance(&self) -> vm::Result<U256> {
self.ext.origin_balance() self.ext.origin_balance()
} }
@ -146,23 +148,23 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
MessageCallResult::Success(*gas, ReturnData::empty()) MessageCallResult::Success(*gas, ReturnData::empty())
} }
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>> { fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
self.ext.extcode(address) self.ext.extcode(address)
} }
fn extcodesize(&self, address: &Address) -> evm::Result<usize> { fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
self.ext.extcodesize(address) self.ext.extcodesize(address)
} }
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()> { fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
self.ext.log(topics, data) self.ext.log(topics, data)
} }
fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256, evm::Error> { fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256, vm::Error> {
self.ext.ret(gas, data) self.ext.ret(gas, data)
} }
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> { fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> {
self.ext.suicide(refund_address) self.ext.suicide(refund_address)
} }

View File

@ -22,7 +22,7 @@ use spec::Spec;
use ethjson; use ethjson;
use ethjson::state::test::ForkSpec; use ethjson::state::test::ForkSpec;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use evm::env_info::EnvInfo; use vm::EnvInfo;
lazy_static! { lazy_static! {
pub static ref FRONTIER: Spec = ethereum::new_frontier_test(); pub static ref FRONTIER: Spec = ethereum::new_frontier_test();

View File

@ -15,6 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
pub use util::*; pub use util::*;
use std::collections::HashSet;
use std::io::Read;
use std::fs::{File, read_dir}; use std::fs::{File, read_dir};
use std::path::Path; use std::path::Path;
use std::ffi::OsString; use std::ffi::OsString;

View File

@ -106,6 +106,11 @@ extern crate semver;
extern crate stats; extern crate stats;
extern crate time; extern crate time;
extern crate transient_hashmap; extern crate transient_hashmap;
extern crate using_queue;
extern crate table;
extern crate bloomable;
extern crate vm;
extern crate wasm;
#[macro_use] #[macro_use]
extern crate log; extern crate log;

View File

@ -15,9 +15,11 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use std::collections::{BTreeMap, HashSet};
use std::sync::Arc;
use util::*; use util::*;
use util::using_queue::{UsingQueue, GetAction}; use using_queue::{UsingQueue, GetAction};
use account_provider::{AccountProvider, SignError as AccountError}; use account_provider::{AccountProvider, SignError as AccountError};
use state::{State, CleanupMode}; use state::{State, CleanupMode};
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockId, CallAnalytics, TransactionId}; use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockId, CallAnalytics, TransactionId};

View File

@ -106,7 +106,7 @@ use std::cmp;
use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap}; use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap};
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use util::{Address, H256, U256, HeapSizeOf}; use util::{Address, H256, U256, HeapSizeOf};
use util::table::Table; use table::Table;
use transaction::*; use transaction::*;
use error::{Error, TransactionError}; use error::{Error, TransactionError};
use client::TransactionImportResult; use client::TransactionImportResult;
@ -1447,7 +1447,7 @@ fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option<HashMap<Addr
#[cfg(test)] #[cfg(test)]
pub mod test { pub mod test {
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::table::*; use table::Table;
use util::*; use util::*;
use ethkey::{Random, Generator}; use ethkey::{Random, Generator};
use error::{Error, TransactionError}; use error::{Error, TransactionError};

View File

@ -16,6 +16,7 @@
extern crate hyper; extern crate hyper;
use std::io::Write;
use hyper::header::ContentType; use hyper::header::ContentType;
use hyper::method::Method; use hyper::method::Method;
use hyper::client::{Request, Response, Client}; use hyper::client::{Request, Response, Client};

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use std::collections::BTreeMap;
use util::*; use util::*;
use state::Account; use state::Account;
use ethjson; use ethjson;
@ -166,7 +168,7 @@ pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option<A
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use util::*; use std::collections::BTreeMap;
use types::account_diff::*; use types::account_diff::*;
use super::{PodAccount, diff_pod}; use super::{PodAccount, diff_pod};

View File

@ -16,6 +16,8 @@
//! State of all accounts in the system expressed in Plain Old Data. //! State of all accounts in the system expressed in Plain Old Data.
use std::fmt;
use std::collections::BTreeMap;
use util::*; use util::*;
use pod_account::{self, PodAccount}; use pod_account::{self, PodAccount};
use types::state_diff::StateDiff; use types::state_diff::StateDiff;
@ -77,7 +79,7 @@ pub fn diff_pod(pre: &PodState, post: &PodState) -> StateDiff {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use util::*; use std::collections::BTreeMap;
use types::state_diff::*; use types::state_diff::*;
use types::account_diff::*; use types::account_diff::*;
use pod_account::PodAccount; use pod_account::PodAccount;

View File

@ -16,6 +16,8 @@
//! Creates and registers client and network services. //! Creates and registers client and network services.
use std::sync::Arc;
use std::path::Path;
use util::*; use util::*;
use io::*; use io::*;
use spec::Spec; use spec::Spec;

View File

@ -16,14 +16,17 @@
//! Parameters for a block chain. //! Parameters for a block chain.
use std::io::Read;
use std::collections::BTreeMap;
use std::path::Path;
use std::sync::Arc;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use super::genesis::Genesis; use super::genesis::Genesis;
use super::seal::Generic as GenericSeal; use super::seal::Generic as GenericSeal;
use evm::action_params::{ActionValue, ActionParams};
use builtin::Builtin; use builtin::Builtin;
use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT}; use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT};
use evm::env_info::EnvInfo; use vm::{EnvInfo, CallType, ActionValue, ActionParams};
use error::Error; use error::Error;
use ethereum; use ethereum;
use ethjson; use ethjson;
@ -36,7 +39,6 @@ use state_db::StateDB;
use state::{Backend, State, Substate}; use state::{Backend, State, Substate};
use state::backend::Basic as BasicBackend; use state::backend::Basic as BasicBackend;
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use evm::CallType;
use util::*; use util::*;
/// Parameters common to ethereum-like blockchains. /// Parameters common to ethereum-like blockchains.
@ -102,14 +104,14 @@ pub struct CommonParams {
impl CommonParams { impl CommonParams {
/// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net. /// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net.
pub fn schedule(&self, block_number: u64) -> ::evm::Schedule { pub fn schedule(&self, block_number: u64) -> ::vm::Schedule {
let mut schedule = ::evm::Schedule::new_post_eip150(usize::max_value(), true, true, true); let mut schedule = ::vm::Schedule::new_post_eip150(usize::max_value(), true, true, true);
self.update_schedule(block_number, &mut schedule); self.update_schedule(block_number, &mut schedule);
schedule schedule
} }
/// Apply common spec config parameters to the schedule. /// Apply common spec config parameters to the schedule.
pub fn update_schedule(&self, block_number: u64, schedule: &mut ::evm::Schedule) { pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) {
schedule.have_create2 = block_number >= self.eip86_transition; schedule.have_create2 = block_number >= self.eip86_transition;
schedule.have_revert = block_number >= self.eip140_transition; schedule.have_revert = block_number >= self.eip140_transition;
schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_static_call = block_number >= self.eip214_transition;
@ -119,8 +121,8 @@ impl CommonParams {
} }
if block_number >= self.dust_protection_transition { if block_number >= self.dust_protection_transition {
schedule.kill_dust = match self.remove_dust_contracts { schedule.kill_dust = match self.remove_dust_contracts {
true => ::evm::CleanDustMode::WithCodeAndStorage, true => ::vm::CleanDustMode::WithCodeAndStorage,
false => ::evm::CleanDustMode::BasicOnly, false => ::vm::CleanDustMode::BasicOnly,
}; };
} }
} }
@ -517,6 +519,7 @@ impl Spec {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::FromStr;
use util::*; use util::*;
use views::*; use views::*;
use tests::helpers::get_temp_state_db; use tests::helpers::get_temp_state_db;
@ -529,19 +532,6 @@ mod tests {
assert!(Spec::load(::std::env::temp_dir(), &[] as &[u8]).is_err()); assert!(Spec::load(::std::env::temp_dir(), &[] as &[u8]).is_err());
} }
#[test]
fn all_spec_files_valid() {
Spec::new_test();
Spec::new_null();
Spec::new_test_constructor();
Spec::new_instant();
Spec::new_test_round();
Spec::new_test_tendermint();
Spec::new_validator_safe_contract();
Spec::new_validator_contract();
Spec::new_validator_multi();
}
#[test] #[test]
fn test_chain() { fn test_chain() {
let test_spec = Spec::new_test(); let test_spec = Spec::new_test();

View File

@ -16,6 +16,9 @@
//! Single account in the system. //! Single account in the system.
use std::fmt;
use std::sync::Arc;
use std::collections::HashMap;
use util::*; use util::*;
use pod_account::*; use pod_account::*;
use rlp::*; use rlp::*;

View File

@ -21,10 +21,13 @@
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::{HashMap, BTreeMap, HashSet};
use std::fmt;
use std::sync::Arc;
use receipt::Receipt; use receipt::Receipt;
use engines::Engine; use engines::Engine;
use evm::env_info::EnvInfo; use vm::EnvInfo;
use error::Error; use error::Error;
use executive::{Executive, TransactOptions}; use executive::{Executive, TransactOptions};
use factory::Factories; use factory::Factories;
@ -982,7 +985,7 @@ mod tests {
use ethkey::Secret; use ethkey::Secret;
use util::{U256, H256, Address, Hashable}; use util::{U256, H256, Address, Hashable};
use tests::helpers::*; use tests::helpers::*;
use evm::env_info::EnvInfo; use vm::EnvInfo;
use spec::*; use spec::*;
use transaction::*; use transaction::*;
use ethcore_logger::init_log; use ethcore_logger::init_log;

View File

@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{VecDeque, HashSet}; use std::collections::{VecDeque, HashSet};
use std::sync::Arc;
use lru_cache::LruCache; use lru_cache::LruCache;
use util::cache::MemoryLruCache; use util::cache::MemoryLruCache;
use util::journaldb::JournalDB; use util::journaldb::JournalDB;
@ -23,7 +24,7 @@ use util::hash::{H256};
use util::hashdb::HashDB; use util::hashdb::HashDB;
use state::{self, Account}; use state::{self, Account};
use header::BlockNumber; use header::BlockNumber;
use util::{Arc, Address, DBTransaction, UtilError, Mutex, Hashable}; use util::{Address, DBTransaction, UtilError, Mutex, Hashable};
use bloom_journal::{Bloom, BloomJournal}; use bloom_journal::{Bloom, BloomJournal};
use db::COL_ACCOUNT_BLOOM; use db::COL_ACCOUNT_BLOOM;
use byteorder::{LittleEndian, ByteOrder}; use byteorder::{LittleEndian, ByteOrder};

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::str::FromStr;
use std::sync::Arc;
use io::IoChannel; use io::IoChannel;
use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockId}; use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockId};
use state::{self, State, CleanupMode}; use state::{self, State, CleanupMode};

View File

@ -1,9 +1,8 @@
//! Tests of EVM integration with transaction execution. //! Tests of EVM integration with transaction execution.
use evm::action_params::{ActionParams, ActionValue}; use std::sync::Arc;
use evm::env_info::EnvInfo; use vm::{EnvInfo, ActionParams, ActionValue, CallType};
use evm::{Factory, VMType}; use evm::{Factory, VMType};
use evm::call_type::CallType;
use executive::Executive; use executive::Executive;
use state::Substate; use state::Substate;
use tests::helpers::*; use tests::helpers::*;

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeMap;
use std::sync::Arc;
use ethkey::KeyPair; use ethkey::KeyPair;
use io::*; use io::*;
use client::{BlockChainClient, Client, ClientConfig}; use client::{BlockChainClient, Client, ClientConfig};
@ -347,7 +349,7 @@ pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_h
for i in start_number .. start_number + count + 1 { for i in start_number .. start_number + count + 1 {
let mut block_header = Header::new(); let mut block_header = Header::new();
block_header.set_gas_limit(test_engine.params().min_gas_limit); block_header.set_gas_limit(test_engine.params().min_gas_limit);
block_header.set_difficulty(U256::from(i).mul(U256([0, 1, 0, 0]))); block_header.set_difficulty(U256::from(i) * U256([0, 1, 0, 0]));
block_header.set_timestamp(rolling_timestamp); block_header.set_timestamp(rolling_timestamp);
block_header.set_number(i as u64); block_header.set_number(i as u64);
block_header.set_parent_hash(parent); block_header.set_parent_hash(parent);

View File

@ -17,7 +17,7 @@
//! Simple executive tracer. //! Simple executive tracer.
use util::{Bytes, Address, U256}; use util::{Bytes, Address, U256};
use evm::action_params::ActionParams; use vm::ActionParams;
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType};
use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::{Tracer, VMTracer, FlatTrace, TraceError};

View File

@ -39,7 +39,7 @@ pub use self::types::filter::{Filter, AddressesFilter};
use util::{Bytes, Address, U256, H256, DBTransaction}; use util::{Bytes, Address, U256, H256, DBTransaction};
use self::trace::{Call, Create}; use self::trace::{Call, Create};
use evm::action_params::ActionParams; use vm::ActionParams;
use header::BlockNumber; use header::BlockNumber;
/// This trait is used by executive to build traces. /// This trait is used by executive to build traces.

View File

@ -17,7 +17,7 @@
//! Nonoperative tracer. //! Nonoperative tracer.
use util::{Bytes, Address, U256}; use util::{Bytes, Address, U256};
use evm::action_params::ActionParams; use vm::ActionParams;
use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::{Tracer, VMTracer, FlatTrace, TraceError};
use trace::trace::{Call, Create, VMTrace, RewardType}; use trace::trace::{Call, Create, VMTrace, RewardType};

View File

@ -18,7 +18,7 @@
use std::fmt; use std::fmt;
use rlp::{Encodable, RlpStream, Decodable, DecoderError, UntrustedRlp}; use rlp::{Encodable, RlpStream, Decodable, DecoderError, UntrustedRlp};
use evm::Error as EvmError; use vm::Error as VmError;
/// Trace evm errors. /// Trace evm errors.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -45,24 +45,24 @@ pub enum Error {
Wasm, Wasm,
} }
impl<'a> From<&'a EvmError> for Error { impl<'a> From<&'a VmError> for Error {
fn from(e: &'a EvmError) -> Self { fn from(e: &'a VmError) -> Self {
match *e { match *e {
EvmError::OutOfGas => Error::OutOfGas, VmError::OutOfGas => Error::OutOfGas,
EvmError::BadJumpDestination { .. } => Error::BadJumpDestination, VmError::BadJumpDestination { .. } => Error::BadJumpDestination,
EvmError::BadInstruction { .. } => Error::BadInstruction, VmError::BadInstruction { .. } => Error::BadInstruction,
EvmError::StackUnderflow { .. } => Error::StackUnderflow, VmError::StackUnderflow { .. } => Error::StackUnderflow,
EvmError::OutOfStack { .. } => Error::OutOfStack, VmError::OutOfStack { .. } => Error::OutOfStack,
EvmError::BuiltIn { .. } => Error::BuiltIn, VmError::BuiltIn { .. } => Error::BuiltIn,
EvmError::Wasm { .. } => Error::Wasm, VmError::Wasm { .. } => Error::Wasm,
EvmError::Internal(_) => Error::Internal, VmError::Internal(_) => Error::Internal,
EvmError::MutableCallInStaticContext => Error::MutableCallInStaticContext, VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext,
} }
} }
} }
impl From<EvmError> for Error { impl From<VmError> for Error {
fn from(e: EvmError) -> Self { fn from(e: VmError) -> Self {
Error::from(&e) Error::from(&e)
} }
} }

View File

@ -20,7 +20,7 @@ use std::ops::Range;
use bloomchain::{Filter as BloomFilter, Bloom, Number}; use bloomchain::{Filter as BloomFilter, Bloom, Number};
use util::Address; use util::Address;
use util::sha3::Hashable; use util::sha3::Hashable;
use util::bloom::Bloomable; use bloomable::Bloomable;
use basic_types::LogBloom; use basic_types::LogBloom;
use trace::flat::FlatTrace; use trace::flat::FlatTrace;
use super::trace::{Action, Res}; use super::trace::{Action, Res};
@ -141,7 +141,7 @@ impl Filter {
mod tests { mod tests {
use util::Address; use util::Address;
use util::sha3::Hashable; use util::sha3::Hashable;
use util::bloom::Bloomable; use bloomable::Bloomable;
use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward};
use trace::flat::FlatTrace; use trace::flat::FlatTrace;
use trace::{Filter, AddressesFilter, TraceError, RewardType}; use trace::{Filter, AddressesFilter, TraceError, RewardType};

View File

@ -18,10 +18,10 @@
use util::{U256, Bytes, Address}; use util::{U256, Bytes, Address};
use util::sha3::Hashable; use util::sha3::Hashable;
use util::bloom::Bloomable; use bloomable::Bloomable;
use rlp::*; use rlp::*;
use evm::action_params::ActionParams; use vm::ActionParams;
use basic_types::LogBloom; use basic_types::LogBloom;
use evm::CallType; use evm::CallType;
use super::error::Error; use super::error::Error;

View File

@ -19,7 +19,9 @@
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
use std::sync::{Condvar as SCondvar, Mutex as SMutex}; use std::sync::{Condvar as SCondvar, Mutex as SMutex, Arc};
use std::cmp;
use std::collections::{VecDeque, HashSet, HashMap};
use util::*; use util::*;
use io::*; use io::*;
use error::*; use error::*;
@ -234,8 +236,8 @@ impl<K: Kind> VerificationQueue<K> {
let scale_verifiers = config.verifier_settings.scale_verifiers; let scale_verifiers = config.verifier_settings.scale_verifiers;
let num_cpus = ::num_cpus::get(); let num_cpus = ::num_cpus::get();
let max_verifiers = min(num_cpus, MAX_VERIFIERS); let max_verifiers = cmp::min(num_cpus, MAX_VERIFIERS);
let default_amount = max(1, min(max_verifiers, config.verifier_settings.num_verifiers)); let default_amount = cmp::max(1, cmp::min(max_verifiers, config.verifier_settings.num_verifiers));
let state = Arc::new((Mutex::new(State::Work(default_amount)), Condvar::new())); let state = Arc::new((Mutex::new(State::Work(default_amount)), Condvar::new()));
let mut verifier_handles = Vec::with_capacity(max_verifiers); let mut verifier_handles = Vec::with_capacity(max_verifiers);
@ -278,8 +280,8 @@ impl<K: Kind> VerificationQueue<K> {
processing: RwLock::new(HashMap::new()), processing: RwLock::new(HashMap::new()),
empty: empty, empty: empty,
ticks_since_adjustment: AtomicUsize::new(0), ticks_since_adjustment: AtomicUsize::new(0),
max_queue_size: max(config.max_queue_size, MIN_QUEUE_LIMIT), max_queue_size: cmp::max(config.max_queue_size, MIN_QUEUE_LIMIT),
max_mem_use: max(config.max_mem_use, MIN_MEM_LIMIT), max_mem_use: cmp::max(config.max_mem_use, MIN_MEM_LIMIT),
scale_verifiers: scale_verifiers, scale_verifiers: scale_verifiers,
verifier_handles: verifier_handles, verifier_handles: verifier_handles,
state: state, state: state,
@ -567,7 +569,7 @@ impl<K: Kind> VerificationQueue<K> {
/// Removes up to `max` verified items from the queue /// Removes up to `max` verified items from the queue
pub fn drain(&self, max: usize) -> Vec<K::Verified> { pub fn drain(&self, max: usize) -> Vec<K::Verified> {
let mut verified = self.verification.verified.lock(); let mut verified = self.verification.verified.lock();
let count = min(max, verified.len()); let count = cmp::min(max, verified.len());
let result = verified.drain(..count).collect::<Vec<_>>(); let result = verified.drain(..count).collect::<Vec<_>>();
let drained_size = result.iter().map(HeapSizeOf::heap_size_of_children).fold(0, |a, c| a + c); let drained_size = result.iter().map(HeapSizeOf::heap_size_of_children).fold(0, |a, c| a + c);
@ -687,8 +689,8 @@ impl<K: Kind> VerificationQueue<K> {
// or below 1. // or below 1.
fn scale_verifiers(&self, target: usize) { fn scale_verifiers(&self, target: usize) {
let current = self.num_verifiers(); let current = self.num_verifiers();
let target = min(self.verifier_handles.len(), target); let target = cmp::min(self.verifier_handles.len(), target);
let target = max(1, target); let target = cmp::max(1, target);
debug!(target: "verification", "Scaling from {} to {} verifiers", current, target); debug!(target: "verification", "Scaling from {} to {} verifiers", current, target);
@ -725,7 +727,6 @@ impl<K: Kind> Drop for VerificationQueue<K> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*;
use io::*; use io::*;
use spec::*; use spec::*;
use super::{BlockQueue, Config, State}; use super::{BlockQueue, Config, State};

View File

@ -21,6 +21,7 @@
//! 2. Signatures verification done in the queue. //! 2. Signatures verification done in the queue.
//! 3. Final verification against the blockchain done before enactment. //! 3. Final verification against the blockchain done before enactment.
use std::collections::HashSet;
use util::*; use util::*;
use engines::Engine; use engines::Engine;
use error::{BlockError, Error}; use error::{BlockError, Error};
@ -264,6 +265,7 @@ fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::{BTreeMap, HashMap};
use util::*; use util::*;
use ethkey::{Random, Generator}; use ethkey::{Random, Generator};
use header::*; use header::*;

View File

@ -8,6 +8,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
rlp = { path = "../../util/rlp" } rlp = { path = "../../util/rlp" }
ethcore-util = { path = "../../util" } ethcore-util = { path = "../../util" }
ethjson = { path = "../../json" } ethjson = { path = "../../json" }
bloomable = { path = "../../util/bloomable" }
[dev-dependencies] [dev-dependencies]
rustc-hex= "1.0" rustc-hex= "1.0"

View File

@ -17,7 +17,7 @@
//! Blockchain filter //! Blockchain filter
use util::{Address, H256, Hashable, H2048}; use util::{Address, H256, Hashable, H2048};
use util::bloom::Bloomable; use bloomable::Bloomable;
use ids::BlockId; use ids::BlockId;
use log_entry::LogEntry; use log_entry::LogEntry;

View File

@ -19,6 +19,7 @@
extern crate ethcore_util as util; extern crate ethcore_util as util;
extern crate ethjson; extern crate ethjson;
extern crate rlp; extern crate rlp;
extern crate bloomable;
#[cfg(test)] #[cfg(test)]
extern crate rustc_hex; extern crate rustc_hex;

View File

@ -18,7 +18,7 @@
use std::ops::Deref; use std::ops::Deref;
use util::{H256, Address, Bytes, HeapSizeOf, Hashable}; use util::{H256, Address, Bytes, HeapSizeOf, Hashable};
use util::bloom::Bloomable; use bloomable::Bloomable;
use rlp::*; use rlp::*;
use {BlockNumber}; use {BlockNumber};
@ -114,8 +114,8 @@ mod tests {
#[test] #[test]
fn test_empty_log_bloom() { fn test_empty_log_bloom() {
let bloom = H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let bloom = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse::<H2048>().unwrap();
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse::<Address>().unwrap();
let log = LogEntry { let log = LogEntry {
address: address, address: address,
topics: vec![], topics: vec![],

14
ethcore/vm/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "vm"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
ethcore-util = { path = "../../util" }
log = "0.3"
common-types = { path = "../types" }
evmjit = { path = "../../evmjit", optional = true }
ethjson = { path = "../../json" }
lazy_static = "0.2"
rlp = { path = "../../util/rlp" }

View File

@ -20,7 +20,7 @@ use util::hash::{H256};
use util::sha3::{Hashable, SHA3_EMPTY}; use util::sha3::{Hashable, SHA3_EMPTY};
use ethjson; use ethjson;
use {CallType}; use call_type::CallType;
use std::sync::Arc; use std::sync::Arc;

100
ethcore/vm/src/error.rs Normal file
View File

@ -0,0 +1,100 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! VM errors module
use util::trie;
use std::fmt;
/// VM errors.
#[derive(Debug, Clone, PartialEq)]
pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas.
/// The state should be reverted to the state from before the
/// transaction execution. But it does not mean that transaction
/// was invalid. Balance still should be transfered and nonce
/// should be increased.
OutOfGas,
/// `BadJumpDestination` is returned when execution tried to move
/// to position that wasn't marked with JUMPDEST instruction
BadJumpDestination {
/// Position the code tried to jump to.
destination: usize
},
/// `BadInstructions` is returned when given instruction is not supported
BadInstruction {
/// Unrecognized opcode
instruction: u8,
},
/// `StackUnderflow` when there is not enough stack elements to execute instruction
StackUnderflow {
/// Invoked instruction
instruction: &'static str,
/// How many stack elements was requested by instruction
wanted: usize,
/// How many elements were on stack
on_stack: usize
},
/// When execution would exceed defined Stack Limit
OutOfStack {
/// Invoked instruction
instruction: &'static str,
/// How many stack elements instruction wanted to push
wanted: usize,
/// What was the stack limit
limit: usize
},
/// Built-in contract failed on given input
BuiltIn(&'static str),
/// When execution tries to modify the state in static context
MutableCallInStaticContext,
/// Likely to cause consensus issues.
Internal(String),
/// Wasm runtime error
Wasm(String),
}
impl From<Box<trie::TrieError>> for Error {
fn from(err: Box<trie::TrieError>) -> Self {
Error::Internal(format!("Internal error: {}", err))
}
}
// impl From<wasm::RuntimeError> for Error {
// fn from(err: wasm::RuntimeError) -> Self {
// Error::Wasm(format!("Runtime error: {:?}", err))
// }
// }
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match *self {
OutOfGas => write!(f, "Out of gas"),
BadJumpDestination { destination } => write!(f, "Bad jump destination {:x}", destination),
BadInstruction { instruction } => write!(f, "Bad instruction {:x}", instruction),
StackUnderflow { instruction, wanted, on_stack } => write!(f, "Stack underflow {} {}/{}", instruction, wanted, on_stack),
OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
BuiltIn(name) => write!(f, "Built-in failed: {}", name),
Internal(ref msg) => write!(f, "Internal error: {}", msg),
MutableCallInStaticContext => write!(f, "Mutable call in static context"),
Wasm(ref msg) => write!(f, "Internal error: {}", msg),
}
}
}
pub type Result<T> = ::std::result::Result<T, Error>;

View File

@ -16,11 +16,13 @@
//! Interface for Evm externalities. //! Interface for Evm externalities.
use std::sync::Arc;
use util::*; use util::*;
use call_type::CallType; use call_type::CallType;
use env_info::EnvInfo; use env_info::EnvInfo;
use schedule::Schedule; use schedule::Schedule;
use evm::{self, ReturnData}; use return_data::ReturnData;
use error::Result;
/// Result of externalities create function. /// Result of externalities create function.
pub enum ContractCreateResult { pub enum ContractCreateResult {
@ -56,22 +58,22 @@ pub enum CreateContractAddress {
/// Externalities interface for EVMs /// Externalities interface for EVMs
pub trait Ext { pub trait Ext {
/// Returns a value for given key. /// Returns a value for given key.
fn storage_at(&self, key: &H256) -> evm::Result<H256>; fn storage_at(&self, key: &H256) -> Result<H256>;
/// Stores a value for given key. /// Stores a value for given key.
fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()>; fn set_storage(&mut self, key: H256, value: H256) -> Result<()>;
/// Determine whether an account exists. /// Determine whether an account exists.
fn exists(&self, address: &Address) -> evm::Result<bool>; fn exists(&self, address: &Address) -> Result<bool>;
/// Determine whether an account exists and is not null (zero balance/nonce, no code). /// Determine whether an account exists and is not null (zero balance/nonce, no code).
fn exists_and_not_null(&self, address: &Address) -> evm::Result<bool>; fn exists_and_not_null(&self, address: &Address) -> Result<bool>;
/// Balance of the origin account. /// Balance of the origin account.
fn origin_balance(&self) -> evm::Result<U256>; fn origin_balance(&self) -> Result<U256>;
/// Returns address balance. /// Returns address balance.
fn balance(&self, address: &Address) -> evm::Result<U256>; fn balance(&self, address: &Address) -> Result<U256>;
/// Returns the hash of one of the 256 most recent complete blocks. /// Returns the hash of one of the 256 most recent complete blocks.
fn blockhash(&mut self, number: &U256) -> H256; fn blockhash(&mut self, number: &U256) -> H256;
@ -99,21 +101,21 @@ pub trait Ext {
) -> MessageCallResult; ) -> MessageCallResult;
/// Returns code at given address /// Returns code at given address
fn extcode(&self, address: &Address) -> evm::Result<Arc<Bytes>>; fn extcode(&self, address: &Address) -> Result<Arc<Bytes>>;
/// Returns code size at given address /// Returns code size at given address
fn extcodesize(&self, address: &Address) -> evm::Result<usize>; fn extcodesize(&self, address: &Address) -> Result<usize>;
/// Creates log entry with given topics and data /// Creates log entry with given topics and data
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> evm::Result<()>; fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()>;
/// Should be called when transaction calls `RETURN` opcode. /// Should be called when transaction calls `RETURN` opcode.
/// Returns gas_left if cost of returning the data is not too high. /// Returns gas_left if cost of returning the data is not too high.
fn ret(self, gas: &U256, data: &ReturnData) -> evm::Result<U256>; fn ret(self, gas: &U256, data: &ReturnData) -> Result<U256>;
/// Should be called when contract commits suicide. /// Should be called when contract commits suicide.
/// Address to which funds should be refunded. /// Address to which funds should be refunded.
fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> ; fn suicide(&mut self, refund_address: &Address) -> Result<()> ;
/// Returns schedule. /// Returns schedule.
fn schedule(&self) -> &Schedule; fn schedule(&self) -> &Schedule;

48
ethcore/vm/src/lib.rs Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Virtual machines support library
extern crate ethcore_util as util;
extern crate common_types as types;
extern crate ethjson;
extern crate rlp;
mod action_params;
mod call_type;
mod env_info;
mod schedule;
mod ext;
mod return_data;
mod error;
pub mod tests;
pub use action_params::{ActionParams, ActionValue};
pub use call_type::CallType;
pub use env_info::{EnvInfo, LastHashes};
pub use schedule::{Schedule, CleanDustMode};
pub use ext::{Ext, MessageCallResult, ContractCreateResult, CreateContractAddress};
pub use return_data::{ReturnData, GasLeft};
pub use error::{Error, Result};
/// Virtual Machine interface
pub trait Vm {
/// This function should be used to execute transaction.
/// It returns either an error, a known amount of gas left, or parameters to be used
/// to compute the final gas left.
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
}

View File

@ -0,0 +1,68 @@
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Return data structures
use util::U256;
/// Return data buffer. Holds memory from a previous call and a slice into that memory.
#[derive(Debug)]
pub struct ReturnData {
mem: Vec<u8>,
offset: usize,
size: usize,
}
impl ::std::ops::Deref for ReturnData {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.mem[self.offset..self.offset + self.size]
}
}
impl ReturnData {
/// Create empty `ReturnData`.
pub fn empty() -> Self {
ReturnData {
mem: Vec::new(),
offset: 0,
size: 0,
}
}
/// Create `ReturnData` from give buffer and slice.
pub fn new(mem: Vec<u8>, offset: usize, size: usize) -> Self {
ReturnData {
mem: mem,
offset: offset,
size: size,
}
}
}
/// Gas Left: either it is a known value, or it needs to be computed by processing
/// a return instruction.
#[derive(Debug)]
pub enum GasLeft {
/// Known gas left
Known(U256),
/// Return or Revert instruction must be processed.
NeedsReturn {
/// Amount of gas left.
gas_left: U256,
/// Return data buffer.
data: ReturnData,
/// Apply or revert state changes on revert.
apply_state: bool
},
}

View File

@ -250,6 +250,12 @@ impl Schedule {
} }
} }
impl Default for Schedule {
fn default() -> Self {
Schedule::new_frontier()
}
}
#[test] #[test]
#[cfg(test)] #[cfg(test)]
fn schedule_evm_assumptions() { fn schedule_evm_assumptions() {
@ -260,3 +266,4 @@ fn schedule_evm_assumptions() {
assert_eq!(s1.quad_coeff_div, 512); assert_eq!(s1.quad_coeff_div, 512);
assert_eq!(s2.quad_coeff_div, 512); assert_eq!(s2.quad_coeff_div, 512);
} }

187
ethcore/vm/src/tests.rs Normal file
View File

@ -0,0 +1,187 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use util::{H256, U256, Address, Bytes};
use {
CallType, Schedule, EnvInfo,
ReturnData, Ext, ContractCreateResult, MessageCallResult,
CreateContractAddress, Result, GasLeft,
};
pub struct FakeLogEntry {
pub topics: Vec<H256>,
pub data: Bytes
}
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum FakeCallType {
Call, Create
}
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct FakeCall {
pub call_type: FakeCallType,
pub gas: U256,
pub sender_address: Option<Address>,
pub receive_address: Option<Address>,
pub value: Option<U256>,
pub data: Bytes,
pub code_address: Option<Address>,
}
/// Fake externalities test structure.
///
/// Can't do recursive calls.
#[derive(Default)]
pub struct FakeExt {
pub store: HashMap<H256, H256>,
pub suicides: HashSet<Address>,
pub calls: HashSet<FakeCall>,
pub sstore_clears: usize,
pub depth: usize,
pub blockhashes: HashMap<U256, H256>,
pub codes: HashMap<Address, Arc<Bytes>>,
pub logs: Vec<FakeLogEntry>,
pub info: EnvInfo,
pub schedule: Schedule,
pub balances: HashMap<Address, U256>,
}
// similar to the normal `finalize` function, but ignoring NeedsReturn.
pub fn test_finalize(res: Result<GasLeft>) -> Result<U256> {
match res {
Ok(GasLeft::Known(gas)) => Ok(gas),
Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented.
Err(e) => Err(e),
}
}
impl FakeExt {
pub fn new() -> Self {
FakeExt::default()
}
}
impl Ext for FakeExt {
fn storage_at(&self, key: &H256) -> Result<H256> {
Ok(self.store.get(key).unwrap_or(&H256::new()).clone())
}
fn set_storage(&mut self, key: H256, value: H256) -> Result<()> {
self.store.insert(key, value);
Ok(())
}
fn exists(&self, address: &Address) -> Result<bool> {
Ok(self.balances.contains_key(address))
}
fn exists_and_not_null(&self, address: &Address) -> Result<bool> {
Ok(self.balances.get(address).map_or(false, |b| !b.is_zero()))
}
fn origin_balance(&self) -> Result<U256> {
unimplemented!()
}
fn balance(&self, address: &Address) -> Result<U256> {
Ok(self.balances[address])
}
fn blockhash(&mut self, number: &U256) -> H256 {
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Create,
gas: *gas,
sender_address: None,
receive_address: None,
value: Some(*value),
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,
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Call,
gas: *gas,
sender_address: Some(sender_address.clone()),
receive_address: Some(receive_address.clone()),
value: value,
data: data.to_vec(),
code_address: Some(code_address.clone())
});
MessageCallResult::Success(*gas, ReturnData::empty())
}
fn extcode(&self, address: &Address) -> Result<Arc<Bytes>> {
Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone())
}
fn extcodesize(&self, address: &Address) -> Result<usize> {
Ok(self.codes.get(address).map_or(0, |c| c.len()))
}
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()> {
self.logs.push(FakeLogEntry {
topics: topics,
data: data.to_vec()
});
Ok(())
}
fn ret(self, _gas: &U256, _data: &ReturnData) -> Result<U256> {
unimplemented!();
}
fn suicide(&mut self, refund_address: &Address) -> Result<()> {
self.suicides.insert(refund_address.clone());
Ok(())
}
fn schedule(&self) -> &Schedule {
&self.schedule
}
fn env_info(&self) -> &EnvInfo {
&self.info
}
fn depth(&self) -> usize {
self.depth
}
fn inc_sstore_clears(&mut self) {
self.sstore_clears += 1;
}
}

13
ethcore/wasm/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "wasm"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
ethcore-util = { path = "../../util" }
log = "0.3"
parity-wasm = "0.12"
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" }

View File

@ -61,6 +61,21 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
&[I32; 4], &[I32; 4],
Some(I32), Some(I32),
), ),
Static(
"_ccall",
&[I32; 6],
Some(I32),
),
Static(
"_dcall",
&[I32; 5],
Some(I32),
),
Static(
"_scall",
&[I32; 5],
Some(I32),
),
Static( Static(
"abort", "abort",
&[I32], &[I32],
@ -72,48 +87,57 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
None, None,
), ),
Static( Static(
"invoke_vii", "abortOnCannotGrowMemory",
&[I32; 3], &[I32; 0],
None, Some(I32)
),
Static(
"invoke_vi",
&[I32; 2],
None,
),
Static(
"invoke_v",
&[I32],
None,
),
Static(
"invoke_iii",
&[I32; 3],
Some(I32),
),
Static(
"___resumeException",
&[I32],
None,
), ),
/*
THIS IS EXPERIMENTAL RUST-ONLY RUNTIME EXTERNS, THEY ARE SUBJECT TO CHANGE
AVOID YOUR WASM CONTAINS ANY OF THESE OTHERWISE
EITHER FACE THE NEED OF HARDFORK
OR YOU CAN STUCK ON SPECIFIC RUST VERSION FOR WASM COMPILATION
*/
Static( Static(
"_rust_begin_unwind", "_rust_begin_unwind",
&[I32; 4], &[I32; 4],
None, None,
), ),
Static(
"___cxa_find_matching_catch_2",
&[],
Some(I32),
),
Static(
"___gxx_personality_v0",
&[I32; 6],
Some(I32),
),
Static( Static(
"_emscripten_memcpy_big", "_emscripten_memcpy_big",
&[I32; 3], &[I32; 3],
Some(I32), Some(I32),
) ),
Static(
"___syscall6",
&[I32; 2],
Some(I32),
),
Static(
"___syscall140",
&[I32; 2],
Some(I32)
),
Static(
"___syscall146",
&[I32; 2],
Some(I32)
),
Static(
"___syscall54",
&[I32; 2],
Some(I32)
),
Static(
"_llvm_trap",
&[I32; 0],
None
),
Static(
"___setErrNo",
&[I32; 1],
None
),
]; ];

View File

@ -16,6 +16,14 @@
//! Wasm Interpreter //! Wasm Interpreter
extern crate vm;
extern crate ethcore_util as util;
#[macro_use] extern crate log;
extern crate ethcore_logger;
extern crate byteorder;
extern crate parity_wasm;
extern crate wasm_utils;
mod runtime; mod runtime;
mod ptr; mod ptr;
mod call_args; mod call_args;
@ -30,11 +38,9 @@ const DEFAULT_STACK_SPACE: u32 = 5 * 1024 * 1024;
use parity_wasm::{interpreter, elements}; use parity_wasm::{interpreter, elements};
use parity_wasm::interpreter::ModuleInstanceInterface; use parity_wasm::interpreter::ModuleInstanceInterface;
use wasm_utils;
use evm::{self, GasLeft, ReturnData}; use vm::{GasLeft, ReturnData, ActionParams};
use action_params::ActionParams; use self::runtime::{Runtime, RuntimeContext};
use self::runtime::Runtime;
pub use self::runtime::Error as RuntimeError; pub use self::runtime::Error as RuntimeError;
@ -56,9 +62,9 @@ impl WasmInterpreter {
} }
} }
impl evm::Evm for WasmInterpreter { impl vm::Vm for WasmInterpreter {
fn exec(&mut self, params: ActionParams, ext: &mut ::ext::Ext) -> evm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
use parity_wasm::elements::Deserialize; use parity_wasm::elements::Deserialize;
let code = params.code.expect("exec is only called on contract with code; qed"); let code = params.code.expect("exec is only called on contract with code; qed");
@ -74,7 +80,7 @@ impl evm::Evm for WasmInterpreter {
.expect("Linear memory to exist in wasm runtime"); .expect("Linear memory to exist in wasm runtime");
if params.gas > ::std::u64::MAX.into() { if params.gas > ::std::u64::MAX.into() {
return Err(evm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned())); return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned()));
} }
let mut runtime = Runtime::with_params( let mut runtime = Runtime::with_params(
@ -82,6 +88,7 @@ impl evm::Evm for WasmInterpreter {
env_memory, env_memory,
DEFAULT_STACK_SPACE, DEFAULT_STACK_SPACE,
params.gas.low_u64(), params.gas.low_u64(),
RuntimeContext::new(params.address, params.sender),
); );
let mut cursor = ::std::io::Cursor::new(&*code); let mut cursor = ::std::io::Cursor::new(&*code);
@ -90,7 +97,7 @@ impl evm::Evm for WasmInterpreter {
elements::Module::deserialize( elements::Module::deserialize(
&mut cursor &mut cursor
).map_err(|err| { ).map_err(|err| {
evm::Error::Wasm(format!("Error deserializing contract code ({:?})", err)) vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err))
})? })?
); );
@ -111,7 +118,7 @@ impl evm::Evm for WasmInterpreter {
interpreter::env_native_module(env_instance, native_bindings(&mut runtime)) interpreter::env_native_module(env_instance, native_bindings(&mut runtime))
.map_err(|err| { .map_err(|err| {
// todo: prefer explicit panic here also? // todo: prefer explicit panic here also?
evm::Error::Wasm(format!("Error instantiating native bindings: {:?}", err)) vm::Error::Wasm(format!("Error instantiating native bindings: {:?}", err))
})? })?
) )
).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32)); ).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
@ -119,13 +126,13 @@ impl evm::Evm for WasmInterpreter {
let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals)) let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals))
.map_err(|err| { .map_err(|err| {
trace!(target: "wasm", "Error adding contract module: {:?}", err); trace!(target: "wasm", "Error adding contract module: {:?}", err);
evm::Error::from(RuntimeError::Interpreter(err)) vm::Error::from(RuntimeError::Interpreter(err))
})?; })?;
module_instance.execute_export("_call", execution_params) module_instance.execute_export("_call", execution_params)
.map_err(|err| { .map_err(|err| {
trace!(target: "wasm", "Error executing contract: {:?}", err); trace!(target: "wasm", "Error executing contract: {:?}", err);
evm::Error::from(RuntimeError::Interpreter(err)) vm::Error::from(RuntimeError::Interpreter(err))
})?; })?;
} }
@ -157,3 +164,9 @@ fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'
functions: ::std::borrow::Cow::from(env::SIGNATURES), functions: ::std::borrow::Cow::from(env::SIGNATURES),
} }
} }
impl From<runtime::Error> for vm::Error {
fn from(err: runtime::Error) -> vm::Error {
vm::Error::Wasm(format!("WASM runtime-error: {:?}", err))
}
}

View File

@ -20,11 +20,11 @@ use std::sync::Arc;
use byteorder::{LittleEndian, ByteOrder}; use byteorder::{LittleEndian, ByteOrder};
use ext; use vm;
use parity_wasm::interpreter; use parity_wasm::interpreter;
use util::{Address, H256, U256}; use util::{Address, H256, U256};
use vm::CallType;
use super::ptr::{WasmPtr, Error as PtrError}; use super::ptr::{WasmPtr, Error as PtrError};
use super::call_args::CallArgs; use super::call_args::CallArgs;
@ -57,22 +57,38 @@ impl From<PtrError> for Error {
} }
} }
pub struct RuntimeContext {
address: Address,
sender: Address,
}
impl RuntimeContext {
pub fn new(address: Address, sender: Address) -> Self {
RuntimeContext {
address: address,
sender: sender,
}
}
}
/// Runtime enviroment data for wasm contract execution /// Runtime enviroment data for wasm contract execution
pub struct Runtime<'a> { pub struct Runtime<'a> {
gas_counter: u64, gas_counter: u64,
gas_limit: u64, gas_limit: u64,
dynamic_top: u32, dynamic_top: u32,
ext: &'a mut ext::Ext, ext: &'a mut vm::Ext,
memory: Arc<interpreter::MemoryInstance>, memory: Arc<interpreter::MemoryInstance>,
context: RuntimeContext,
} }
impl<'a> Runtime<'a> { impl<'a> Runtime<'a> {
/// New runtime for wasm contract with specified params /// New runtime for wasm contract with specified params
pub fn with_params<'b>( pub fn with_params<'b>(
ext: &'b mut ext::Ext, ext: &'b mut vm::Ext,
memory: Arc<interpreter::MemoryInstance>, memory: Arc<interpreter::MemoryInstance>,
stack_space: u32, stack_space: u32,
gas_limit: u64, gas_limit: u64,
context: RuntimeContext,
) -> Runtime<'b> { ) -> Runtime<'b> {
Runtime { Runtime {
gas_counter: 0, gas_counter: 0,
@ -80,6 +96,7 @@ impl<'a> Runtime<'a> {
dynamic_top: stack_space, dynamic_top: stack_space,
memory: memory, memory: memory,
ext: ext, ext: ext,
context: context,
} }
} }
@ -139,7 +156,7 @@ impl<'a> Runtime<'a> {
trace!(target: "wasm", "runtime: create contract"); trace!(target: "wasm", "runtime: create contract");
let mut context = context; let mut context = context;
let result_ptr = context.value_stack.pop_as::<i32>()? as u32; let result_ptr = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " result_ptr: {:?}", result_ptr); trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
let code_len = context.value_stack.pop_as::<i32>()? as u32; let code_len = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " code_len: {:?}", code_len); trace!(target: "wasm", " code_len: {:?}", code_len);
let code_ptr = context.value_stack.pop_as::<i32>()? as u32; let code_ptr = context.value_stack.pop_as::<i32>()? as u32;
@ -153,20 +170,141 @@ impl<'a> Runtime<'a> {
.map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))? .map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))?
.into(); .into();
match self.ext.create(&gas_left, &endowment, &code, ext::CreateContractAddress::FromSenderAndCodeHash) { match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
ext::ContractCreateResult::Created(address, gas_left) => { vm::ContractCreateResult::Created(address, gas_left) => {
self.memory.set(result_ptr, &*address)?; self.memory.set(result_ptr, &*address)?;
self.gas_counter = self.gas_limit - gas_left.low_u64(); self.gas_counter = self.gas_limit - gas_left.low_u64();
trace!(target: "wasm", "runtime: create contract success (@{:?})", address); trace!(target: "wasm", "runtime: create contract success (@{:?})", address);
Ok(Some(0i32.into())) Ok(Some(0i32.into()))
}, },
ext::ContractCreateResult::Failed => { vm::ContractCreateResult::Failed => {
trace!(target: "wasm", "runtime: create contract fail"); trace!(target: "wasm", "runtime: create contract fail");
Ok(Some((-1i32).into())) Ok(Some((-1i32).into()))
} }
} }
} }
pub fn call(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{
//
// method signature:
// fn (
// address: *const u8,
// val_ptr: *const u8,
// input_ptr: *const u8,
// input_len: u32,
// result_ptr: *mut u8,
// result_len: u32,
// ) -> i32
self.do_call(true, CallType::Call, context)
}
fn call_code(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{
//
// signature (same as static call):
// fn (
// address: *const u8,
// input_ptr: *const u8,
// input_len: u32,
// result_ptr: *mut u8,
// result_len: u32,
// ) -> i32
self.do_call(false, CallType::CallCode, context)
}
fn do_call(
&mut self,
use_val: bool,
call_type: CallType,
context: interpreter::CallerContext,
)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{
trace!(target: "wasm", "runtime: call code");
let mut context = context;
let result_alloc_len = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " result_len: {:?}", result_alloc_len);
let result_ptr = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " result_ptr: {:?}", result_ptr);
let input_len = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " input_len: {:?}", input_len);
let input_ptr = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " input_ptr: {:?}", input_ptr);
let val = if use_val { Some(self.pop_u256(&mut context)?) }
else { None };
trace!(target: "wasm", " val: {:?}", val);
let address = self.pop_address(&mut context)?;
trace!(target: "wasm", " address: {:?}", address);
if let Some(ref val) = val {
let address_balance = self.ext.balance(&self.context.address)
.map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))?;
if &address_balance < val {
trace!(target: "wasm", "runtime: call failed due to balance check");
return Ok(Some((-1i32).into()));
}
}
let mut result = Vec::with_capacity(result_alloc_len as usize);
result.resize(result_alloc_len as usize, 0);
let gas = self.gas_left()
.map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))?
.into();
// todo: optimize to use memory views once it's in
let payload = self.memory.get(input_ptr, input_len as usize)?;
let call_result = self.ext.call(
&gas,
&self.context.sender,
&self.context.address,
val,
&payload,
&address,
&mut result[..],
call_type,
);
match call_result {
vm::MessageCallResult::Success(gas_left, _) => {
self.gas_counter = self.gas_limit - gas_left.low_u64();
self.memory.set(result_ptr, &result)?;
Ok(Some(0i32.into()))
},
vm::MessageCallResult::Failed => {
Ok(Some((-1i32).into()))
}
}
}
pub fn static_call(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{
// signature (same as code call):
// fn (
// address: *const u8,
// input_ptr: *const u8,
// input_len: u32,
// result_ptr: *mut u8,
// result_len: u32,
// ) -> i32
self.do_call(false, CallType::StaticCall, context)
}
/// Allocate memory using the wasm stack params /// Allocate memory using the wasm stack params
pub fn malloc(&mut self, context: interpreter::CallerContext) pub fn malloc(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
@ -338,6 +476,15 @@ impl<'a> interpreter::UserFunctionExecutor for Runtime<'a> {
"_create" => { "_create" => {
self.create(context) self.create(context)
}, },
"_ccall" => {
self.call(context)
},
"_dcall" => {
self.call_code(context)
},
"_scall" => {
self.static_call(context)
},
"_debug" => { "_debug" => {
self.debug_log(context) self.debug_log(context)
}, },
@ -348,7 +495,7 @@ impl<'a> interpreter::UserFunctionExecutor for Runtime<'a> {
self.mem_copy(context) self.mem_copy(context)
}, },
_ => { _ => {
trace!("Unknown env func: '{}'", name); trace!(target: "wasm", "Trapped due to unhandled function: '{}'", name);
self.user_trap(context) self.user_trap(context)
} }
} }

View File

@ -15,20 +15,20 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc; use std::sync::Arc;
use byteorder::{LittleEndian, ByteOrder};
use super::super::tests::{FakeExt, FakeCall, FakeCallType};
use super::WasmInterpreter;
use evm::{self, Evm, GasLeft};
use action_params::{ActionParams, ActionValue};
use util::{U256, H256, Address}; use util::{U256, H256, Address};
use super::WasmInterpreter;
use vm::{self, Vm, GasLeft, ActionParams, ActionValue};
use vm::tests::{FakeCall, FakeExt, FakeCallType};
macro_rules! load_sample { macro_rules! load_sample {
($name: expr) => { ($name: expr) => {
include_bytes!(concat!("../../../res/wasm-tests/compiled/", $name)).to_vec() include_bytes!(concat!("../../res/wasm-tests/compiled/", $name)).to_vec()
} }
} }
fn test_finalize(res: Result<GasLeft, evm::Error>) -> Result<U256, evm::Error> { fn test_finalize(res: Result<GasLeft, vm::Error>) -> Result<U256, vm::Error> {
match res { match res {
Ok(GasLeft::Known(gas)) => Ok(gas), Ok(GasLeft::Known(gas)) => Ok(gas),
Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented. Ok(GasLeft::NeedsReturn{..}) => unimplemented!(), // since ret is unimplemented.
@ -85,7 +85,7 @@ fn logger() {
}; };
println!("ext.store: {:?}", ext.store); println!("ext.store: {:?}", ext.store);
assert_eq!(gas_left, U256::from(99581)); assert_eq!(gas_left, U256::from(99590));
let address_val: H256 = address.into(); let address_val: H256 = address.into();
assert_eq!( assert_eq!(
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"), ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
@ -136,7 +136,7 @@ fn identity() {
} }
}; };
assert_eq!(gas_left, U256::from(99_689)); assert_eq!(gas_left, U256::from(99_687));
assert_eq!( assert_eq!(
Address::from_slice(&result), Address::from_slice(&result),
@ -170,7 +170,7 @@ fn dispersion() {
} }
}; };
assert_eq!(gas_left, U256::from(99_402)); assert_eq!(gas_left, U256::from(99_423));
assert_eq!( assert_eq!(
result, result,
@ -199,7 +199,7 @@ fn suicide_not() {
} }
}; };
assert_eq!(gas_left, U256::from(99_703)); assert_eq!(gas_left, U256::from(99_656));
assert_eq!( assert_eq!(
result, result,
@ -233,12 +233,14 @@ fn suicide() {
} }
}; };
assert_eq!(gas_left, U256::from(99_747)); assert_eq!(gas_left, U256::from(99_740));
assert!(ext.suicides.contains(&refund)); assert!(ext.suicides.contains(&refund));
} }
#[test] #[test]
fn create() { fn create() {
::ethcore_logger::init_log();
let mut params = ActionParams::default(); let mut params = ActionParams::default();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("creator.wasm"))); params.code = Some(Arc::new(load_sample!("creator.wasm")));
@ -262,7 +264,7 @@ fn create() {
assert!(ext.calls.contains( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Create, call_type: FakeCallType::Create,
gas: U256::from(99_778), gas: U256::from(99_767),
sender_address: None, sender_address: None,
receive_address: None, receive_address: None,
value: Some(1_000_000_000.into()), value: Some(1_000_000_000.into()),
@ -270,5 +272,119 @@ fn create() {
code_address: None, code_address: None,
} }
)); ));
assert_eq!(gas_left, U256::from(99_768)); assert_eq!(gas_left, U256::from(99_759));
}
#[test]
fn call_code() {
::ethcore_logger::init_log();
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let mut params = ActionParams::default();
params.sender = sender.clone();
params.address = receiver.clone();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("call_code.wasm")));
params.data = Some(Vec::new());
params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(99_061),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
data: vec![1u8, 2, 3, 5, 7, 11],
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(94196));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
}
#[test]
fn call_static() {
::ethcore_logger::init_log();
let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let mut params = ActionParams::default();
params.sender = sender.clone();
params.address = receiver.clone();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("call_static.wasm")));
params.data = Some(Vec::new());
params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Static call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(99_061),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
data: vec![1u8, 2, 3, 5, 7, 11],
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(94196));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);
}
// Realloc test
#[test]
fn realloc() {
let code = load_sample!("realloc.wasm");
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(vec![0u8]);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Realloc should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(gas_left, U256::from(98326));
assert_eq!(result, vec![0u8; 2]);
} }

View File

@ -25,7 +25,7 @@ extern crate panic_hook;
use std::{env, fmt, process}; use std::{env, fmt, process};
use std::num::ParseIntError; use std::num::ParseIntError;
use docopt::Docopt; use docopt::Docopt;
use rustc_hex::{FromHex, FromHexError}; use rustc_hex::{ToHex, FromHex, FromHexError};
use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address}; use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address};
use std::io; use std::io;
@ -170,7 +170,7 @@ fn main() {
fn display(keypair: KeyPair, mode: DisplayMode) -> String { fn display(keypair: KeyPair, mode: DisplayMode) -> String {
match mode { match mode {
DisplayMode::KeyPair => format!("{}", keypair), DisplayMode::KeyPair => format!("{}", keypair),
DisplayMode::Secret => format!("{:?}", keypair.secret()), DisplayMode::Secret => format!("{}", keypair.secret().to_hex()),
DisplayMode::Public => format!("{:?}", keypair.public()), DisplayMode::Public => format!("{:?}", keypair.public()),
DisplayMode::Address => format!("{:?}", keypair.address()), DisplayMode::Address => format!("{:?}", keypair.address()),
} }
@ -248,9 +248,9 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let expected = let expected =
"secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 "secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2
public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4
address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected); assert_eq!(execute(command).unwrap(), expected);
} }
@ -261,7 +261,7 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let expected = "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55".to_owned(); let expected = "aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2".to_owned();
assert_eq!(execute(command).unwrap(), expected); assert_eq!(execute(command).unwrap(), expected);
} }
@ -272,7 +272,7 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let expected = "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124".to_owned(); let expected = "c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4".to_owned();
assert_eq!(execute(command).unwrap(), expected); assert_eq!(execute(command).unwrap(), expected);
} }
@ -283,7 +283,7 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let expected = "26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); let expected = "006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected); assert_eq!(execute(command).unwrap(), expected);
} }

View File

@ -17,6 +17,7 @@
use std::fmt; use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use rustc_hex::ToHex;
use secp256k1::key; use secp256k1::key;
use bigint::hash::H256; use bigint::hash::H256;
use {Error, SECP256K1}; use {Error, SECP256K1};
@ -26,6 +27,12 @@ pub struct Secret {
inner: H256, inner: H256,
} }
impl ToHex for Secret {
fn to_hex(&self) -> String {
self.inner.to_hex()
}
}
impl fmt::Debug for Secret { impl fmt::Debug for Secret {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "Secret: 0x{:x}{:x}..{:x}{:x}", self.inner[0], self.inner[1], self.inner[30], self.inner[31]) write!(fmt, "Secret: 0x{:x}{:x}..{:x}{:x}", self.inner[0], self.inner[1], self.inner[30], self.inner[31])

Some files were not shown because too many files have changed in this diff Show More