Kovan WASM fork code (#7849)

* kovan fork code

* introduce ethcore level vm_factory and let it fail

* fix json tests

* wasmcosts as option

* review changes

* wasm costs in parser

* fix evm tests

* review fixes

* fix test

* remove redundant json field
This commit is contained in:
Nikolay Volf 2018-02-19 14:27:42 +03:00 committed by Rando
parent 605f3b0381
commit 684322cd6f
28 changed files with 337 additions and 160 deletions

1
Cargo.lock generated
View File

@ -554,7 +554,6 @@ dependencies = [
"ethcore-network 1.9.0", "ethcore-network 1.9.0",
"ethcore-transaction 0.1.0", "ethcore-transaction 0.1.0",
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"evm 0.1.0",
"futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1", "hashdb 0.1.1",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -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<Vm> { 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<Vm> { 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()))
@ -68,8 +68,8 @@ impl Factory {
} }
} }
fn can_fit_in_usize(gas: U256) -> bool { fn can_fit_in_usize(gas: &U256) -> bool {
gas == U256::from(gas.low_u64() as usize) gas == &U256::from(gas.low_u64() as usize)
} }
} }
@ -95,7 +95,7 @@ impl Default for Factory {
#[test] #[test]
fn test_create_vm() { fn test_create_vm() {
let _vm = Factory::default().create(U256::zero()); let _vm = Factory::default().create(&U256::zero());
} }
/// Create tests by injecting different VM factories /// Create tests by injecting different VM factories

View File

@ -913,8 +913,13 @@ mod tests {
use rustc_hex::FromHex; use rustc_hex::FromHex;
use vmtype::VMType; use vmtype::VMType;
use factory::Factory; use factory::Factory;
use vm::{ActionParams, ActionValue}; use vm::{Vm, ActionParams, ActionValue};
use vm::tests::{FakeExt, test_finalize}; use vm::tests::{FakeExt, test_finalize};
use ethereum_types::U256;
fn interpreter(gas: &U256) -> Box<Vm> {
Factory::new(VMType::Interpreter, 1).create(gas)
}
#[test] #[test]
fn should_not_fail_on_tracing_mem() { fn should_not_fail_on_tracing_mem() {
@ -931,7 +936,7 @@ mod tests {
ext.tracing = true; ext.tracing = true;
let gas_left = { let gas_left = {
let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas); let mut vm = interpreter(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -953,7 +958,7 @@ mod tests {
ext.tracing = true; ext.tracing = true;
let err = { let err = {
let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas); let mut vm = interpreter(&params.gas);
test_finalize(vm.exec(params, &mut ext)).err().unwrap() test_finalize(vm.exec(params, &mut ext)).err().unwrap()
}; };

View File

@ -38,7 +38,7 @@ fn test_add(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -58,7 +58,7 @@ fn test_sha3(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -78,7 +78,7 @@ fn test_address(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -100,7 +100,7 @@ fn test_origin(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -122,7 +122,7 @@ fn test_sender(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -157,7 +157,7 @@ fn test_extcodecopy(factory: super::Factory) {
ext.codes.insert(sender, Arc::new(sender_code)); ext.codes.insert(sender, Arc::new(sender_code));
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -177,7 +177,7 @@ fn test_log_empty(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -209,7 +209,7 @@ fn test_log_sender(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -234,7 +234,7 @@ fn test_blockhash(factory: super::Factory) {
ext.blockhashes.insert(U256::zero(), blockhash.clone()); ext.blockhashes.insert(U256::zero(), blockhash.clone());
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -256,7 +256,7 @@ fn test_calldataload(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -277,7 +277,7 @@ fn test_author(factory: super::Factory) {
ext.info.author = author; ext.info.author = author;
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -297,7 +297,7 @@ fn test_timestamp(factory: super::Factory) {
ext.info.timestamp = timestamp; ext.info.timestamp = timestamp;
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -317,7 +317,7 @@ fn test_number(factory: super::Factory) {
ext.info.number = number; ext.info.number = number;
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -337,7 +337,7 @@ fn test_difficulty(factory: super::Factory) {
ext.info.difficulty = difficulty; ext.info.difficulty = difficulty;
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -357,7 +357,7 @@ fn test_gas_limit(factory: super::Factory) {
ext.info.gas_limit = gas_limit; ext.info.gas_limit = gas_limit;
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -375,7 +375,7 @@ fn test_mul(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -393,7 +393,7 @@ fn test_sub(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -411,7 +411,7 @@ fn test_div(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -429,7 +429,7 @@ fn test_div_zero(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -447,7 +447,7 @@ fn test_mod(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -466,7 +466,7 @@ fn test_smod(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -485,7 +485,7 @@ fn test_sdiv(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -504,7 +504,7 @@ fn test_exp(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -524,7 +524,7 @@ fn test_comparison(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -545,7 +545,7 @@ fn test_signed_comparison(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -566,7 +566,7 @@ fn test_bitops(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -589,7 +589,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -610,7 +610,7 @@ fn test_byte(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -629,7 +629,7 @@ fn test_signextend(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -649,7 +649,7 @@ fn test_badinstruction_int() {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let err = { let err = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err() test_finalize(vm.exec(params, &mut ext)).unwrap_err()
}; };
@ -669,7 +669,7 @@ fn test_pop(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -689,7 +689,7 @@ fn test_extops(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -712,7 +712,7 @@ fn test_jumps(factory: super::Factory) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -740,7 +740,7 @@ fn test_calls(factory: super::Factory) {
}; };
let gas_left = { let gas_left = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap() test_finalize(vm.exec(params, &mut ext)).unwrap()
}; };
@ -779,7 +779,7 @@ fn test_create_in_staticcall(factory: super::Factory) {
ext.is_static = true; ext.is_static = true;
let err = { let err = {
let mut vm = factory.create(params.gas); let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err() test_finalize(vm.exec(params, &mut ext)).unwrap_err()
}; };

View File

@ -16,7 +16,6 @@ memorydb = { path = "../../util/memorydb" }
patricia-trie = { path = "../../util/patricia_trie" } patricia-trie = { path = "../../util/patricia_trie" }
ethcore-network = { path = "../../util/network" } ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" } ethcore-io = { path = "../../util/io" }
evm = { path = "../evm" }
hashdb = { path = "../../util/hashdb" } hashdb = { path = "../../util/hashdb" }
heapsize = "0.4" heapsize = "0.4"
vm = { path = "../vm" } vm = { path = "../vm" }

View File

@ -60,7 +60,6 @@ extern crate ethcore_bytes as bytes;
extern crate ethcore_transaction as transaction; extern crate ethcore_transaction as transaction;
extern crate ethereum_types; extern crate ethereum_types;
extern crate ethcore; extern crate ethcore;
extern crate evm;
extern crate hashdb; extern crate hashdb;
extern crate heapsize; extern crate heapsize;
extern crate futures; extern crate futures;

View File

@ -0,0 +1,74 @@
{
"name": "Kovan (Test)",
"dataDir": "kovan-test",
"engine": {
"authorityRound": {
"params": {
"stepDuration": "4",
"blockReward": "0x4563918244F40000",
"validators" : {
"list": [
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
"0x00427feae2419c15b89d1c21af10d1b6650a4d3d",
"0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c",
"0x0020ee4Be0e2027d76603cB751eE069519bA81A1",
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
"0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A",
"0x00E6d2b931F55a3f1701c7389d592a7778897879",
"0x00e4a10650e5a6D6001C38ff8E64F97016a1645c",
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"validateScoreTransition": 1000000,
"validateStepTransition": 1500000,
"maximumUncleCountTransition": 5067000,
"maximumUncleCount": 0
}
}
},
"params": {
"gasLimitBoundDivisor": "0x400",
"registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2A",
"forkBlock": 4297256,
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
"validateReceiptsTransition" : 1000000,
"eip155Transition": 1000000,
"validateChainIdTransition": 1000000,
"eip140Transition": 5067000,
"eip211Transition": 5067000,
"eip214Transition": 5067000,
"eip658Transition": 5067000,
"wasmActivationTransition": 10
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"gasLimit": "0x5B8D80"
},
"accounts": {
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } },
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
},
"nodes": [
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
"enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303",
"enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303",
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303"
]
}

View File

@ -46,9 +46,9 @@ use encoded;
use engines::{EthEngine, EpochTransition}; use engines::{EthEngine, EpochTransition};
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 vm::{EnvInfo, LastHashes};
use evm::{Factory as EvmFactory, Schedule}; use evm::Schedule;
use executive::{Executive, Executed, TransactOptions, contract_address}; use executive::{Executive, Executed, TransactOptions, contract_address};
use factory::Factories; use factory::{Factories, VmFactory};
use header::{BlockNumber, Header, Seal}; use header::{BlockNumber, Header, Seal};
use io::*; use io::*;
use log_entry::LocalizedLogEntry; use log_entry::LocalizedLogEntry;
@ -186,7 +186,7 @@ impl Client {
let trie_factory = TrieFactory::new(trie_spec); let trie_factory = TrieFactory::new(trie_spec);
let factories = Factories { let factories = Factories {
vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size), vm: VmFactory::new(config.vm_type.clone(), config.jump_table_size),
trie: trie_factory, trie: trie_factory,
accountdb: Default::default(), accountdb: Default::default(),
}; };
@ -1912,7 +1912,7 @@ impl MiningBlockChainClient for Client {
block block
} }
fn vm_factory(&self) -> &EvmFactory { fn vm_factory(&self) -> &VmFactory {
&self.factories.vm &self.factories.vm
} }

View File

@ -19,12 +19,11 @@
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use journaldb; use {factory, journaldb, trie, kvdb_memorydb, bytes};
use {trie, kvdb_memorydb, bytes};
use kvdb::{self, KeyValueDB}; use kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state}; use {state, state_db, client, executive, trace, transaction, db, spec, pod_state};
use factory::Factories; use factory::Factories;
use evm::{self, VMType, FinalizationResult}; use evm::{VMType, FinalizationResult};
use vm::{self, ActionParams}; use vm::{self, ActionParams};
/// EVM test Error. /// EVM test Error.
@ -119,7 +118,7 @@ impl<'a> EvmTestClient<'a> {
fn factories() -> Factories { fn factories() -> Factories {
Factories { Factories {
vm: evm::Factory::new(VMType::Interpreter, 5 * 1024), vm: factory::VmFactory::new(VMType::Interpreter, 5 * 1024),
trie: trie::TrieFactory::new(trie::TrieSpec::Secure), trie: trie::TrieFactory::new(trie::TrieSpec::Secure),
accountdb: Default::default(), accountdb: Default::default(),
} }

View File

@ -45,7 +45,8 @@ use filter::Filter;
use log_entry::LocalizedLogEntry; use log_entry::LocalizedLogEntry;
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome}; use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
use error::{ImportResult, Error as EthcoreError}; use error::{ImportResult, Error as EthcoreError};
use evm::{Factory as EvmFactory, VMType}; use evm::VMType;
use factory::VmFactory;
use vm::Schedule; use vm::Schedule;
use miner::{Miner, MinerService}; use miner::{Miner, MinerService};
use spec::Spec; use spec::Spec;
@ -96,7 +97,7 @@ pub struct TestBlockChainClient {
/// Spec /// Spec
pub spec: Spec, pub spec: Spec,
/// VM Factory /// VM Factory
pub vm_factory: EvmFactory, pub vm_factory: VmFactory,
/// Timestamp assigned to latest sealed block /// Timestamp assigned to latest sealed block
pub latest_block_timestamp: RwLock<u64>, pub latest_block_timestamp: RwLock<u64>,
/// Ancient block info. /// Ancient block info.
@ -167,7 +168,7 @@ impl TestBlockChainClient {
queue_size: AtomicUsize::new(0), queue_size: AtomicUsize::new(0),
miner: Arc::new(Miner::with_spec(&spec)), miner: Arc::new(Miner::with_spec(&spec)),
spec: spec, spec: spec,
vm_factory: EvmFactory::new(VMType::Interpreter, 1024 * 1024), vm_factory: VmFactory::new(VMType::Interpreter, 1024 * 1024),
latest_block_timestamp: RwLock::new(10_000_000), latest_block_timestamp: RwLock::new(10_000_000),
ancient_block: RwLock::new(None), ancient_block: RwLock::new(None),
first_block: RwLock::new(None), first_block: RwLock::new(None),
@ -394,7 +395,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
block.reopen(&*self.spec.engine) block.reopen(&*self.spec.engine)
} }
fn vm_factory(&self) -> &EvmFactory { fn vm_factory(&self) -> &VmFactory {
&self.vm_factory &self.vm_factory
} }

View File

@ -22,7 +22,8 @@ use blockchain::TreeRoute;
use encoded; use encoded;
use vm::LastHashes; use vm::LastHashes;
use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError}; use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError};
use evm::{Factory as EvmFactory, Schedule}; use evm::Schedule;
use factory::VmFactory;
use executive::Executed; use executive::Executed;
use filter::Filter; use filter::Filter;
use header::{BlockNumber}; use header::{BlockNumber};
@ -298,7 +299,7 @@ pub trait MiningBlockChainClient: BlockChainClient {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock; fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
/// Returns EvmFactory. /// Returns EvmFactory.
fn vm_factory(&self) -> &EvmFactory; fn vm_factory(&self) -> &VmFactory;
/// Broadcast a block proposal. /// Broadcast a block proposal.
fn broadcast_proposal_block(&self, block: SealedBlock); fn broadcast_proposal_block(&self, block: SealedBlock);

View File

@ -385,11 +385,6 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
self.machine().verify_transaction_basic(t, header) self.machine().verify_transaction_basic(t, header)
} }
/// If this machine supports wasm.
fn supports_wasm(&self) -> bool {
self.machine().supports_wasm()
}
/// Additional information. /// Additional information.
fn additional_params(&self) -> HashMap<String, String> { fn additional_params(&self) -> HashMap<String, String> {
self.machine().additional_params() self.machine().additional_params()

View File

@ -132,6 +132,9 @@ pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(inclu
/// Create a new Musicoin-MCIP3-era spec. /// Create a new Musicoin-MCIP3-era spec.
pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) } pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) }
/// Create new Kovan spec with wasm activated at certain block
pub fn new_kovan_wasm_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/kovan_wasm_test.json")) }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ethereum_types::U256; use ethereum_types::U256;

View File

@ -22,11 +22,12 @@ use ethereum_types::{H256, U256, U512, Address};
use bytes::{Bytes, BytesRef}; use bytes::{Bytes, BytesRef};
use state::{Backend as StateBackend, State, Substate, CleanupMode}; use state::{Backend as StateBackend, State, Substate, CleanupMode};
use machine::EthereumMachine as Machine; use machine::EthereumMachine as Machine;
use vm::EnvInfo;
use error::ExecutionError; use error::ExecutionError;
use evm::{CallType, Factory, Finalize, FinalizationResult}; use evm::{CallType, Finalize, FinalizationResult};
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue}; use vm::{
use wasm; self, Ext, EnvInfo, CreateContractAddress, ReturnData, CleanDustMode, ActionParams,
ActionValue, Schedule,
};
use externalities::*; use externalities::*;
use trace::{self, Tracer, VMTracer}; use trace::{self, Tracer, VMTracer};
use transaction::{Action, SignedTransaction}; use transaction::{Action, SignedTransaction};
@ -38,8 +39,6 @@ pub use executed::{Executed, ExecutionResult};
/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp`
const STACK_SIZE_PER_DEPTH: usize = 24*1024; const STACK_SIZE_PER_DEPTH: usize = 24*1024;
const WASM_MAGIC_NUMBER: &'static [u8; 4] = b"\0asm";
/// Returns new address created from address, nonce, and code hash /// Returns new address created from address, nonce, and code hash
pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option<H256>) { pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option<H256>) {
use rlp::RlpStream; use rlp::RlpStream;
@ -152,14 +151,6 @@ impl TransactOptions<trace::NoopTracer, trace::NoopVMTracer> {
} }
} }
pub fn executor(machine: &Machine, vm_factory: &Factory, params: &ActionParams) -> Box<vm::Vm> {
if machine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(wasm::WasmInterpreter)
} else {
vm_factory.create(params.gas)
}
}
/// Transaction executor. /// Transaction executor.
pub struct Executive<'a, B: 'a + StateBackend> { pub struct Executive<'a, B: 'a + StateBackend> {
state: &'a mut State<B>, state: &'a mut State<B>,
@ -334,6 +325,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
fn exec_vm<T, V>( fn exec_vm<T, V>(
&mut self, &mut self,
schedule: Schedule,
params: ActionParams, params: ActionParams,
unconfirmed_substate: &mut Substate, unconfirmed_substate: &mut Substate,
output_policy: OutputPolicy, output_policy: OutputPolicy,
@ -349,19 +341,20 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let vm_factory = self.state.vm_factory(); let vm_factory = self.state.vm_factory();
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call);
return executor(self.machine, &vm_factory, &params).exec(params, &mut ext).finalize(ext); let mut vm = vm_factory.create(&params, &schedule);
return vm.exec(params, &mut ext).finalize(ext);
} }
// Start in new thread to reset stack // Start in new thread to reset stack
// TODO [todr] No thread builder yet, so we need to reset once for a while // TODO [todr] No thread builder yet, so we need to reset once for a while
// https://github.com/aturon/crossbeam/issues/16 // https://github.com/aturon/crossbeam/issues/16
crossbeam::scope(|scope| { crossbeam::scope(|scope| {
let machine = self.machine;
let vm_factory = self.state.vm_factory(); let vm_factory = self.state.vm_factory();
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
scope.spawn(move || { scope.spawn(move || {
executor(machine, &vm_factory, &params).exec(params, &mut ext).finalize(ext) let mut vm = vm_factory.create(&params, &schedule);
vm.exec(params, &mut ext).finalize(ext)
}) })
}).join() }).join()
} }
@ -471,7 +464,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed")); let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
let res = { let res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer) self.exec_vm(schedule, params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
}; };
vm_tracer.done_subtrace(subvmtracer); vm_tracer.done_subtrace(subvmtracer);
@ -562,9 +555,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed")); let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed"));
let res = { let res = self.exec_vm(
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())), &mut subtracer, &mut subvmtracer) schedule,
}; params,
&mut unconfirmed_substate,
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
&mut subtracer,
&mut subvmtracer
);
vm_tracer.done_subtrace(subvmtracer); vm_tracer.done_subtrace(subvmtracer);
@ -1481,8 +1479,6 @@ mod tests {
params.gas = U256::from(20025); params.gas = U256::from(20025);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.value = ActionValue::Transfer(U256::zero()); params.value = ActionValue::Transfer(U256::zero());
let mut state = get_temp_state_with_factory(factory);
state.add_balance(&sender, &U256::from_str("152d02c7e14af68000000").unwrap(), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default(); let info = EnvInfo::default();
let machine = ::ethereum::new_byzantium_test_machine(); let machine = ::ethereum::new_byzantium_test_machine();
let mut substate = Substate::new(); let mut substate = Substate::new();
@ -1497,4 +1493,60 @@ mod tests {
assert_eq!(output[..], returns[..]); assert_eq!(output[..], returns[..]);
assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0))); assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0)));
} }
fn wasm_sample_code() -> Arc<Vec<u8>> {
Arc::new(
"0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000"
.from_hex()
.unwrap()
)
}
#[test]
fn wasm_activated_test() {
let contract_address = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let mut state = get_temp_state();
state.add_balance(&sender, &U256::from(10000000000u64), CleanupMode::NoEmpty).unwrap();
state.commit().unwrap();
let mut params = ActionParams::default();
params.origin = sender.clone();
params.sender = sender.clone();
params.address = contract_address.clone();
params.gas = U256::from(20025);
params.code = Some(wasm_sample_code());
let mut info = EnvInfo::default();
// 100 > 10
info.number = 100;
// Network with wasm activated at block 10
let machine = ::ethereum::new_kovan_wasm_test_machine();
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
ex.call(params.clone(), &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(result, U256::from(18433));
// Transaction successfully returned sender
assert_eq!(output[..], sender[..]);
// 1 < 10
info.number = 1;
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
ex.call(params, &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(result, U256::from(20025));
// Since transaction errored due to wasm was not activated, result is just empty
assert_eq!(output[..], [0u8; 20][..]);
}
} }

View File

@ -15,14 +15,44 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use trie::TrieFactory; use trie::TrieFactory;
use evm::Factory as EvmFactory;
use account_db::Factory as AccountFactory; use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType};
use vm::{Vm, ActionParams, Schedule};
use wasm::WasmInterpreter;
const WASM_MAGIC_NUMBER: &'static [u8; 4] = b"\0asm";
/// Virtual machine factory
#[derive(Default, Clone)]
pub struct VmFactory {
evm: EvmFactory,
}
impl VmFactory {
pub fn create(&self, params: &ActionParams, schedule: &Schedule) -> Box<Vm> {
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter)
} else {
self.evm.create(&params.gas)
}
}
pub fn new(evm: VMType, cache_size: usize) -> Self {
VmFactory { evm: EvmFactory::new(evm, cache_size) }
}
}
impl From<EvmFactory> for VmFactory {
fn from(evm: EvmFactory) -> Self {
VmFactory { evm: evm }
}
}
/// Collection of factories. /// Collection of factories.
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct Factories { pub struct Factories {
/// factory for evm. /// factory for evm.
pub vm: EvmFactory, pub vm: VmFactory,
/// factory for tries. /// factory for tries.
pub trie: TrieFactory, pub trie: TrieFactory,
/// factory for account databases. /// factory for account databases.

View File

@ -259,7 +259,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec<String> {
&mut tracer, &mut tracer,
&mut vm_tracer, &mut vm_tracer,
)); ));
let mut evm = vm_factory.create(params.gas); let mut evm = vm_factory.create(&params, &machine.schedule(0u64.into()));
let res = evm.exec(params, &mut ex); let res = evm.exec(params, &mut ex);
// a return in finalize will not alter callcreates // a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone(); let callcreates = ex.callcreates.clone();

View File

@ -376,11 +376,6 @@ impl EthereumMachine {
Ok(()) Ok(())
} }
/// If this machine supports wasm.
pub fn supports_wasm(&self) -> bool {
self.params().wasm
}
/// Additional params. /// Additional params.
pub fn additional_params(&self) -> HashMap<String, String> { pub fn additional_params(&self) -> HashMap<String, String> {
hash_map![ hash_map![

View File

@ -109,8 +109,8 @@ pub struct CommonParams {
pub nonce_cap_increment: u64, pub nonce_cap_increment: u64,
/// Enable dust cleanup for contracts. /// Enable dust cleanup for contracts.
pub remove_dust_contracts: bool, pub remove_dust_contracts: bool,
/// Wasm support /// Wasm activation blocknumber, if any disabled initially.
pub wasm: bool, pub wasm_activation_transition: BlockNumber,
/// Gas limit bound divisor (how much gas limit can change per block) /// Gas limit bound divisor (how much gas limit can change per block)
pub gas_limit_bound_divisor: U256, pub gas_limit_bound_divisor: U256,
/// Registrar contract address. /// Registrar contract address.
@ -146,6 +146,9 @@ impl CommonParams {
false => ::vm::CleanDustMode::BasicOnly, false => ::vm::CleanDustMode::BasicOnly,
}; };
} }
if block_number >= self.wasm_activation_transition {
schedule.wasm = Some(Default::default());
}
} }
/// Whether these params contain any bug-fix hard forks. /// Whether these params contain any bug-fix hard forks.
@ -220,12 +223,15 @@ impl From<ethjson::spec::Params> for CommonParams {
), ),
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
wasm: p.wasm.unwrap_or(false),
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
registrar: p.registrar.map_or_else(Address::new, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into),
node_permission_contract: p.node_permission_contract.map(Into::into), node_permission_contract: p.node_permission_contract.map(Into::into),
max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into),
transaction_permission_contract: p.transaction_permission_contract.map(Into::into), transaction_permission_contract: p.transaction_permission_contract.map(Into::into),
wasm_activation_transition: p.wasm_activation_transition.map_or(
BlockNumber::max_value(),
Into::into
),
} }
} }
} }

View File

@ -40,7 +40,7 @@ use executed::{Executed, ExecutionError};
use types::state_diff::StateDiff; use types::state_diff::StateDiff;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use state_db::StateDB; use state_db::StateDB;
use evm::{Factory as EvmFactory}; use factory::VmFactory;
use ethereum_types::{H256, U256, Address}; use ethereum_types::{H256, U256, Address};
use hashdb::{HashDB, AsHashDB}; use hashdb::{HashDB, AsHashDB};
@ -376,7 +376,7 @@ impl<B: Backend> State<B> {
} }
/// Get a VM factory that can execute on this state. /// Get a VM factory that can execute on this state.
pub fn vm_factory(&self) -> EvmFactory { pub fn vm_factory(&self) -> VmFactory {
self.factories.vm.clone() self.factories.vm.clone()
} }

View File

@ -275,7 +275,7 @@ pub fn get_temp_state() -> State<::state_db::StateDB> {
pub fn get_temp_state_with_factory(factory: EvmFactory) -> State<::state_db::StateDB> { pub fn get_temp_state_with_factory(factory: EvmFactory) -> State<::state_db::StateDB> {
let journal_db = get_temp_state_db(); let journal_db = get_temp_state_db();
let mut factories = Factories::default(); let mut factories = Factories::default();
factories.vm = factory; factories.vm = factory.into();
State::new(journal_db, U256::from(0), factories) State::new(journal_db, U256::from(0), factories)
} }

View File

@ -37,7 +37,7 @@ pub mod tests;
pub use action_params::{ActionParams, ActionValue, ParamsType}; pub use action_params::{ActionParams, ActionValue, ParamsType};
pub use call_type::CallType; pub use call_type::CallType;
pub use env_info::{EnvInfo, LastHashes}; pub use env_info::{EnvInfo, LastHashes};
pub use schedule::{Schedule, CleanDustMode}; pub use schedule::{Schedule, CleanDustMode, WasmCosts};
pub use ext::{Ext, MessageCallResult, ContractCreateResult, CreateContractAddress}; pub use ext::{Ext, MessageCallResult, ContractCreateResult, CreateContractAddress};
pub use return_data::{ReturnData, GasLeft}; pub use return_data::{ReturnData, GasLeft};
pub use error::{Error, Result}; pub use error::{Error, Result};

View File

@ -113,8 +113,8 @@ pub struct Schedule {
pub kill_dust: CleanDustMode, pub kill_dust: CleanDustMode,
/// Enable EIP-86 rules /// Enable EIP-86 rules
pub eip86: bool, pub eip86: bool,
/// Wasm extra schedule settings /// Wasm extra schedule settings, if wasm activated
pub wasm: WasmCosts, pub wasm: Option<WasmCosts>,
} }
/// Wasm cost table /// Wasm cost table
@ -231,7 +231,7 @@ impl Schedule {
have_static_call: false, have_static_call: false,
kill_dust: CleanDustMode::Off, kill_dust: CleanDustMode::Off,
eip86: false, eip86: false,
wasm: Default::default(), wasm: None,
} }
} }
@ -294,9 +294,17 @@ impl Schedule {
have_static_call: false, have_static_call: false,
kill_dust: CleanDustMode::Off, kill_dust: CleanDustMode::Off,
eip86: false, eip86: false,
wasm: Default::default(), wasm: None,
} }
} }
/// Returns wasm schedule
///
/// May panic if there is no wasm schedule
pub fn wasm(&self) -> &WasmCosts {
// *** Prefer PANIC here instead of silently breaking consensus! ***
self.wasm.as_ref().expect("Wasm schedule expected to exist while checking wasm contract. Misconfigured client?")
}
} }
impl Default for Schedule { impl Default for Schedule {

View File

@ -76,15 +76,23 @@ pub fn test_finalize(res: Result<GasLeft>) -> Result<U256> {
} }
impl FakeExt { impl FakeExt {
/// New fake externalities
pub fn new() -> Self { pub fn new() -> Self {
FakeExt::default() FakeExt::default()
} }
/// New fake externalities with byzantium schedule rules
pub fn new_byzantium() -> Self { pub fn new_byzantium() -> Self {
let mut ext = FakeExt::default(); let mut ext = FakeExt::default();
ext.schedule = Schedule::new_byzantium(); ext.schedule = Schedule::new_byzantium();
ext ext
} }
/// Alter fake externalities to allow wasm
pub fn with_wasm(mut self) -> Self {
self.schedule.wasm = Some(Default::default());
self
}
} }
impl Ext for FakeExt { impl Ext for FakeExt {

View File

@ -68,7 +68,7 @@ impl From<runtime::Error> for vm::Error {
impl vm::Vm for WasmInterpreter { impl vm::Vm for WasmInterpreter {
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
let (module, data) = parser::payload(&params, ext.schedule())?; let (module, data) = parser::payload(&params, ext.schedule().wasm())?;
let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error)?; let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error)?;
@ -79,8 +79,8 @@ impl vm::Vm for WasmInterpreter {
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolover) &wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolover)
).map_err(Error)?; ).map_err(Error)?;
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm.opcodes_div) / let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
U256::from(ext.schedule().wasm.opcodes_mul); U256::from(ext.schedule().wasm().opcodes_mul);
if adjusted_gas > ::std::u64::MAX.into() if adjusted_gas > ::std::u64::MAX.into()
{ {
@ -111,8 +111,8 @@ impl vm::Vm for WasmInterpreter {
// total_charge <- static_region * 2^32 * 2^16 // total_charge <- static_region * 2^32 * 2^16
// total_charge ∈ [0..2^64) if static_region ∈ [0..2^16) // total_charge ∈ [0..2^64) if static_region ∈ [0..2^16)
// qed // qed
assert!(runtime.schedule().wasm.initial_mem < 1 << 16); assert!(runtime.schedule().wasm().initial_mem < 1 << 16);
runtime.charge(|s| initial_memory as u64 * s.wasm.initial_mem as u64)?; runtime.charge(|s| initial_memory as u64 * s.wasm().initial_mem as u64)?;
let module_instance = module_instance.run_start(&mut runtime).map_err(Error)?; let module_instance = module_instance.run_start(&mut runtime).map_err(Error)?;
@ -148,8 +148,8 @@ impl vm::Vm for WasmInterpreter {
}; };
let gas_left = let gas_left =
U256::from(gas_left) * U256::from(ext.schedule().wasm.opcodes_mul) U256::from(gas_left) * U256::from(ext.schedule().wasm().opcodes_mul)
/ U256::from(ext.schedule().wasm.opcodes_div); / U256::from(ext.schedule().wasm().opcodes_div);
if result.is_empty() { if result.is_empty() {
trace!(target: "wasm", "Contract execution result is empty."); trace!(target: "wasm", "Contract execution result is empty.");

View File

@ -21,21 +21,21 @@ use wasm_utils::{self, rules};
use parity_wasm::elements::{self, Deserialize}; use parity_wasm::elements::{self, Deserialize};
use parity_wasm::peek_size; use parity_wasm::peek_size;
fn gas_rules(schedule: &vm::Schedule) -> rules::Set { fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set {
rules::Set::new({ rules::Set::new({
let mut vals = ::std::collections::HashMap::with_capacity(4); let mut vals = ::std::collections::HashMap::with_capacity(4);
vals.insert(rules::InstructionType::Load, schedule.wasm.mem as u32); vals.insert(rules::InstructionType::Load, wasm_costs.mem as u32);
vals.insert(rules::InstructionType::Store, schedule.wasm.mem as u32); vals.insert(rules::InstructionType::Store, wasm_costs.mem as u32);
vals.insert(rules::InstructionType::Div, schedule.wasm.div as u32); vals.insert(rules::InstructionType::Div, wasm_costs.div as u32);
vals.insert(rules::InstructionType::Mul, schedule.wasm.mul as u32); vals.insert(rules::InstructionType::Mul, wasm_costs.mul as u32);
vals vals
}).with_grow_cost(schedule.wasm.grow_mem) }).with_grow_cost(wasm_costs.grow_mem)
} }
/// Splits payload to code and data according to params.params_type, also /// Splits payload to code and data according to params.params_type, also
/// loads the module instance from payload and injects gas counter according /// loads the module instance from payload and injects gas counter according
/// to schedule. /// to schedule.
pub fn payload<'a>(params: &'a vm::ActionParams, schedule: &vm::Schedule) pub fn payload<'a>(params: &'a vm::ActionParams, wasm_costs: &vm::WasmCosts)
-> Result<(elements::Module, &'a [u8]), vm::Error> -> Result<(elements::Module, &'a [u8]), vm::Error>
{ {
let code = match params.code { let code = match params.code {
@ -70,7 +70,7 @@ pub fn payload<'a>(params: &'a vm::ActionParams, schedule: &vm::Schedule)
let contract_module = wasm_utils::inject_gas_counter( let contract_module = wasm_utils::inject_gas_counter(
deserialized_module, deserialized_module,
&gas_rules(schedule), &gas_rules(wasm_costs),
); );
let data = match params.params_type { let data = match params.params_type {

View File

@ -168,7 +168,7 @@ impl<'a> Runtime<'a> {
pub fn adjusted_charge<F>(&mut self, f: F) -> Result<()> pub fn adjusted_charge<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(&vm::Schedule) -> u64 where F: FnOnce(&vm::Schedule) -> u64
{ {
self.charge(|schedule| f(schedule) * schedule.wasm.opcodes_div as u64 / schedule.wasm.opcodes_mul as u64) self.charge(|schedule| f(schedule) * schedule.wasm().opcodes_div as u64 / schedule.wasm().opcodes_mul as u64)
} }
/// Charge gas provided by the closure /// Charge gas provided by the closure
@ -195,8 +195,8 @@ impl<'a> Runtime<'a> {
{ {
self.overflow_charge(|schedule| self.overflow_charge(|schedule|
f(schedule) f(schedule)
.and_then(|x| x.checked_mul(schedule.wasm.opcodes_div as u64)) .and_then(|x| x.checked_mul(schedule.wasm().opcodes_div as u64))
.map(|x| x / schedule.wasm.opcodes_mul as u64) .map(|x| x / schedule.wasm().opcodes_mul as u64)
) )
} }
@ -373,8 +373,8 @@ impl<'a> Runtime<'a> {
// todo: optimize to use memory views once it's in // todo: optimize to use memory views once it's in
let payload = self.memory.get(input_ptr, input_len as usize)?; let payload = self.memory.get(input_ptr, input_len as usize)?;
let adjusted_gas = match gas.checked_mul(self.ext.schedule().wasm.opcodes_div as u64) let adjusted_gas = match gas.checked_mul(self.ext.schedule().wasm().opcodes_div as u64)
.map(|x| x / self.ext.schedule().wasm.opcodes_mul as u64) .map(|x| x / self.ext.schedule().wasm().opcodes_mul as u64)
{ {
Some(x) => x, Some(x) => x,
None => { None => {
@ -400,8 +400,8 @@ impl<'a> Runtime<'a> {
vm::MessageCallResult::Success(gas_left, _) => { vm::MessageCallResult::Success(gas_left, _) => {
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas // cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64 gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64; / self.ext.schedule().wasm().opcodes_mul as u64;
self.memory.set(result_ptr, &result)?; self.memory.set(result_ptr, &result)?;
Ok(0i32.into()) Ok(0i32.into())
@ -409,8 +409,8 @@ impl<'a> Runtime<'a> {
vm::MessageCallResult::Reverted(gas_left, _) => { vm::MessageCallResult::Reverted(gas_left, _) => {
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas // cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64 gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64; / self.ext.schedule().wasm().opcodes_mul as u64;
self.memory.set(result_ptr, &result)?; self.memory.set(result_ptr, &result)?;
Ok((-1i32).into()) Ok((-1i32).into())
@ -438,14 +438,14 @@ impl<'a> Runtime<'a> {
fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<()> fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<()>
{ {
self.charge(|schedule| schedule.wasm.static_address as u64)?; self.charge(|schedule| schedule.wasm().static_address as u64)?;
self.memory.set(ptr, &*val)?; self.memory.set(ptr, &*val)?;
Ok(()) Ok(())
} }
fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<()> { fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<()> {
let value: H256 = val.into(); let value: H256 = val.into();
self.charge(|schedule| schedule.wasm.static_u256 as u64)?; self.charge(|schedule| schedule.wasm().static_u256 as u64)?;
self.memory.set(ptr, &*value)?; self.memory.set(ptr, &*value)?;
Ok(()) Ok(())
} }
@ -485,8 +485,8 @@ impl<'a> Runtime<'a> {
self.adjusted_charge(|schedule| schedule.create_data_gas as u64 * code.len() as u64)?; self.adjusted_charge(|schedule| schedule.create_data_gas as u64 * code.len() as u64)?;
let gas_left: U256 = U256::from(self.gas_left()?) let gas_left: U256 = U256::from(self.gas_left()?)
* U256::from(self.ext.schedule().wasm.opcodes_mul) * U256::from(self.ext.schedule().wasm().opcodes_mul)
/ U256::from(self.ext.schedule().wasm.opcodes_div); / U256::from(self.ext.schedule().wasm().opcodes_div);
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) { match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
vm::ContractCreateResult::Created(address, gas_left) => { vm::ContractCreateResult::Created(address, gas_left) => {
@ -494,8 +494,8 @@ impl<'a> Runtime<'a> {
self.gas_counter = self.gas_limit - self.gas_counter = self.gas_limit -
// this cannot overflow, since initial gas is in [0..u64::max) range, // this cannot overflow, since initial gas is in [0..u64::max) range,
// and gas_left cannot be bigger // and gas_left cannot be bigger
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64 gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64; / self.ext.schedule().wasm().opcodes_mul as u64;
trace!(target: "wasm", "runtime: create contract success (@{:?})", address); trace!(target: "wasm", "runtime: create contract success (@{:?})", address);
Ok(0i32.into()) Ok(0i32.into())
}, },
@ -508,8 +508,8 @@ impl<'a> Runtime<'a> {
self.gas_counter = self.gas_limit - self.gas_counter = self.gas_limit -
// this cannot overflow, since initial gas is in [0..u64::max) range, // this cannot overflow, since initial gas is in [0..u64::max) range,
// and gas_left cannot be bigger // and gas_left cannot be bigger
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64 gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64; / self.ext.schedule().wasm().opcodes_mul as u64;
Ok((-1i32).into()) Ok((-1i32).into())
}, },

View File

@ -43,7 +43,7 @@ macro_rules! reqrep_test {
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.data = Some($input); params.data = Some($input);
let mut fake_ext = FakeExt::new(); let mut fake_ext = FakeExt::new().with_wasm();
fake_ext.info = $info; fake_ext.info = $info;
fake_ext.blockhashes = $block_hashes; fake_ext.blockhashes = $block_hashes;
@ -79,7 +79,7 @@ fn empty() {
params.address = address.clone(); params.address = address.clone();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -108,7 +108,7 @@ fn logger() {
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -157,7 +157,7 @@ fn identity() {
params.sender = sender.clone(); params.sender = sender.clone();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -192,7 +192,7 @@ fn dispersion() {
params.data = Some(vec![ params.data = Some(vec![
0u8, 125, 197, 255, 19 0u8, 125, 197, 255, 19
]); ]);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -220,7 +220,7 @@ fn suicide_not() {
params.data = Some(vec![ params.data = Some(vec![
0u8 0u8
]); ]);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -253,7 +253,7 @@ fn suicide() {
args.extend(refund.to_vec()); args.extend(refund.to_vec());
params.data = Some(args); params.data = Some(args);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -280,7 +280,7 @@ fn create() {
params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]); params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]);
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -324,7 +324,7 @@ fn call_msg() {
params.code = Some(Arc::new(load_sample!("call.wasm"))); params.code = Some(Arc::new(load_sample!("call.wasm")));
params.data = Some(Vec::new()); params.data = Some(Vec::new());
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
ext.balances.insert(receiver.clone(), U256::from(10000000000u64)); ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
let gas_left = { let gas_left = {
@ -367,7 +367,7 @@ fn call_code() {
params.data = Some(Vec::new()); params.data = Some(Vec::new());
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -414,7 +414,7 @@ fn call_static() {
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
params.code_address = contract_address.clone(); params.code_address = contract_address.clone();
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -454,7 +454,7 @@ fn realloc() {
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.data = Some(vec![0u8]); params.data = Some(vec![0u8]);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -476,7 +476,7 @@ fn alloc() {
params.gas = U256::from(10_000_000); params.gas = U256::from(10_000_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.data = Some(vec![0u8]); params.data = Some(vec![0u8]);
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -502,7 +502,7 @@ fn storage_read() {
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(code)); params.code = Some(Arc::new(code));
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into()); ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into());
let (gas_left, result) = { let (gas_left, result) = {
@ -529,7 +529,7 @@ fn keccak() {
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.data = Some(b"something".to_vec()); params.data = Some(b"something".to_vec());
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -664,7 +664,7 @@ fn storage_metering() {
::ethcore_logger::init_log(); ::ethcore_logger::init_log();
// #1 // #1
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let code = Arc::new(load_sample!("setter.wasm")); let code = Arc::new(load_sample!("setter.wasm"));
let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
@ -805,7 +805,7 @@ fn embedded_keccak() {
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.params_type = vm::ParamsType::Embedded; params.params_type = vm::ParamsType::Embedded;
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();
@ -833,7 +833,7 @@ fn events() {
params.code = Some(Arc::new(code)); params.code = Some(Arc::new(code));
params.data = Some(b"something".to_vec()); params.data = Some(b"something".to_vec());
let mut ext = FakeExt::new(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter();

View File

@ -98,8 +98,6 @@ pub struct Params {
pub nonce_cap_increment: Option<Uint>, pub nonce_cap_increment: Option<Uint>,
/// See `CommonParams` docs. /// See `CommonParams` docs.
pub remove_dust_contracts : Option<bool>, pub remove_dust_contracts : Option<bool>,
/// Wasm support flag
pub wasm: Option<bool>,
/// See `CommonParams` docs. /// See `CommonParams` docs.
#[serde(rename="gasLimitBoundDivisor")] #[serde(rename="gasLimitBoundDivisor")]
#[serde(deserialize_with="uint::validate_non_zero")] #[serde(deserialize_with="uint::validate_non_zero")]
@ -118,6 +116,9 @@ pub struct Params {
/// Transaction permission contract address. /// Transaction permission contract address.
#[serde(rename="transactionPermissionContract")] #[serde(rename="transactionPermissionContract")]
pub transaction_permission_contract: Option<Address>, pub transaction_permission_contract: Option<Address>,
/// Wasm activation block height, if not activated from start
#[serde(rename="wasmActivationTransition")]
pub wasm_activation_transition: Option<Uint>,
} }
#[cfg(test)] #[cfg(test)]
@ -137,7 +138,8 @@ mod tests {
"minGasLimit": "0x1388", "minGasLimit": "0x1388",
"accountStartNonce": "0x01", "accountStartNonce": "0x01",
"gasLimitBoundDivisor": "0x20", "gasLimitBoundDivisor": "0x20",
"maxCodeSize": "0x1000" "maxCodeSize": "0x1000",
"wasmActivationTransition": "0x1010"
}"#; }"#;
let deserialized: Params = serde_json::from_str(s).unwrap(); let deserialized: Params = serde_json::from_str(s).unwrap();
@ -149,6 +151,7 @@ mod tests {
assert_eq!(deserialized.account_start_nonce, Some(Uint(U256::from(0x01)))); assert_eq!(deserialized.account_start_nonce, Some(Uint(U256::from(0x01))));
assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20))); assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20)));
assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000)))); assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000))));
assert_eq!(deserialized.wasm_activation_transition, Some(Uint(U256::from(0x1010))));
} }
#[test] #[test]