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:
parent
605f3b0381
commit
684322cd6f
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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)",
|
||||||
|
@ -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
|
||||||
|
@ -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(¶ms.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(¶ms.gas);
|
||||||
test_finalize(vm.exec(params, &mut ext)).err().unwrap()
|
test_finalize(vm.exec(params, &mut ext)).err().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.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(¶ms.gas);
|
||||||
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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" }
|
||||||
|
@ -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;
|
||||||
|
74
ethcore/res/ethereum/kovan_wasm_test.json
Normal file
74
ethcore/res/ethereum/kovan_wasm_test.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
|
@ -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(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
let mut ext = self.as_externalities(OriginInfo::from(¶ms), 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, ¶ms).exec(params, &mut ext).finalize(ext);
|
let mut vm = vm_factory.create(¶ms, &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(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
||||||
|
|
||||||
scope.spawn(move || {
|
scope.spawn(move || {
|
||||||
executor(machine, &vm_factory, ¶ms).exec(params, &mut ext).finalize(ext)
|
let mut vm = vm_factory.create(¶ms, &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][..]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(¶ms.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.
|
||||||
|
@ -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(¶ms, &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();
|
||||||
|
@ -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![
|
||||||
|
@ -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
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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};
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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(¶ms, ext.schedule())?;
|
let (module, data) = parser::payload(¶ms, 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.");
|
||||||
|
@ -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 {
|
||||||
|
@ -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())
|
||||||
},
|
},
|
||||||
|
@ -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();
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user