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-transaction 0.1.0",
"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)",
"hashdb 0.1.1",
"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
/// Might choose implementation depending on supplied gas.
#[cfg(feature = "jit")]
pub fn create(&self, gas: U256) -> Box<Vm> {
pub fn create(&self, gas: &U256) -> Box<Vm> {
match self.evm {
VMType::Jit => {
Box::new(super::jit::JitEvm::default())
@ -49,7 +49,7 @@ impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
#[cfg(not(feature = "jit"))]
pub fn create(&self, gas: U256) -> Box<Vm> {
pub fn create(&self, gas: &U256) -> Box<Vm> {
match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
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 {
gas == U256::from(gas.low_u64() as usize)
fn can_fit_in_usize(gas: &U256) -> bool {
gas == &U256::from(gas.low_u64() as usize)
}
}
@ -95,7 +95,7 @@ impl Default for Factory {
#[test]
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

View File

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

View File

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

View File

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

View File

@ -60,7 +60,6 @@ extern crate ethcore_bytes as bytes;
extern crate ethcore_transaction as transaction;
extern crate ethereum_types;
extern crate ethcore;
extern crate evm;
extern crate hashdb;
extern crate heapsize;
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 error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
use vm::{EnvInfo, LastHashes};
use evm::{Factory as EvmFactory, Schedule};
use evm::Schedule;
use executive::{Executive, Executed, TransactOptions, contract_address};
use factory::Factories;
use factory::{Factories, VmFactory};
use header::{BlockNumber, Header, Seal};
use io::*;
use log_entry::LocalizedLogEntry;
@ -186,7 +186,7 @@ impl Client {
let trie_factory = TrieFactory::new(trie_spec);
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,
accountdb: Default::default(),
};
@ -1912,7 +1912,7 @@ impl MiningBlockChainClient for Client {
block
}
fn vm_factory(&self) -> &EvmFactory {
fn vm_factory(&self) -> &VmFactory {
&self.factories.vm
}

View File

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

View File

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

View File

@ -22,7 +22,8 @@ use blockchain::TreeRoute;
use encoded;
use vm::LastHashes;
use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError};
use evm::{Factory as EvmFactory, Schedule};
use evm::Schedule;
use factory::VmFactory;
use executive::Executed;
use filter::Filter;
use header::{BlockNumber};
@ -298,7 +299,7 @@ pub trait MiningBlockChainClient: BlockChainClient {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
/// Returns EvmFactory.
fn vm_factory(&self) -> &EvmFactory;
fn vm_factory(&self) -> &VmFactory;
/// Broadcast a block proposal.
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)
}
/// If this machine supports wasm.
fn supports_wasm(&self) -> bool {
self.machine().supports_wasm()
}
/// Additional information.
fn additional_params(&self) -> HashMap<String, String> {
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.
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)]
mod tests {
use ethereum_types::U256;

View File

@ -22,11 +22,12 @@ use ethereum_types::{H256, U256, U512, Address};
use bytes::{Bytes, BytesRef};
use state::{Backend as StateBackend, State, Substate, CleanupMode};
use machine::EthereumMachine as Machine;
use vm::EnvInfo;
use error::ExecutionError;
use evm::{CallType, Factory, Finalize, FinalizationResult};
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue};
use wasm;
use evm::{CallType, Finalize, FinalizationResult};
use vm::{
self, Ext, EnvInfo, CreateContractAddress, ReturnData, CleanDustMode, ActionParams,
ActionValue, Schedule,
};
use externalities::*;
use trace::{self, Tracer, VMTracer};
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`
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
pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option<H256>) {
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.
pub struct Executive<'a, B: 'a + StateBackend> {
state: &'a mut State<B>,
@ -334,6 +325,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
fn exec_vm<T, V>(
&mut self,
schedule: Schedule,
params: ActionParams,
unconfirmed_substate: &mut Substate,
output_policy: OutputPolicy,
@ -349,19 +341,20 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
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);
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
// TODO [todr] No thread builder yet, so we need to reset once for a while
// https://github.com/aturon/crossbeam/issues/16
crossbeam::scope(|scope| {
let machine = self.machine;
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);
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()
}
@ -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 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);
@ -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 res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())), &mut subtracer, &mut subvmtracer)
};
let res = self.exec_vm(
schedule,
params,
&mut unconfirmed_substate,
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
&mut subtracer,
&mut subvmtracer
);
vm_tracer.done_subtrace(subvmtracer);
@ -1481,8 +1479,6 @@ mod tests {
params.gas = U256::from(20025);
params.code = Some(Arc::new(code));
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 machine = ::ethereum::new_byzantium_test_machine();
let mut substate = Substate::new();
@ -1497,4 +1493,60 @@ mod tests {
assert_eq!(output[..], returns[..]);
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/>.
use trie::TrieFactory;
use evm::Factory as EvmFactory;
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.
#[derive(Default, Clone)]
pub struct Factories {
/// factory for evm.
pub vm: EvmFactory,
pub vm: VmFactory,
/// factory for tries.
pub trie: TrieFactory,
/// 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 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);
// a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone();

View File

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

View File

@ -109,8 +109,8 @@ pub struct CommonParams {
pub nonce_cap_increment: u64,
/// Enable dust cleanup for contracts.
pub remove_dust_contracts: bool,
/// Wasm support
pub wasm: bool,
/// Wasm activation blocknumber, if any disabled initially.
pub wasm_activation_transition: BlockNumber,
/// Gas limit bound divisor (how much gas limit can change per block)
pub gas_limit_bound_divisor: U256,
/// Registrar contract address.
@ -146,6 +146,9 @@ impl CommonParams {
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.
@ -220,12 +223,15 @@ impl From<ethjson::spec::Params> for CommonParams {
),
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
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(),
registrar: p.registrar.map_or_else(Address::new, 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),
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 transaction::SignedTransaction;
use state_db::StateDB;
use evm::{Factory as EvmFactory};
use factory::VmFactory;
use ethereum_types::{H256, U256, Address};
use hashdb::{HashDB, AsHashDB};
@ -376,7 +376,7 @@ impl<B: Backend> State<B> {
}
/// 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()
}

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> {
let journal_db = get_temp_state_db();
let mut factories = Factories::default();
factories.vm = factory;
factories.vm = factory.into();
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 call_type::CallType;
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 return_data::{ReturnData, GasLeft};
pub use error::{Error, Result};

View File

@ -113,8 +113,8 @@ pub struct Schedule {
pub kill_dust: CleanDustMode,
/// Enable EIP-86 rules
pub eip86: bool,
/// Wasm extra schedule settings
pub wasm: WasmCosts,
/// Wasm extra schedule settings, if wasm activated
pub wasm: Option<WasmCosts>,
}
/// Wasm cost table
@ -231,7 +231,7 @@ impl Schedule {
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip86: false,
wasm: Default::default(),
wasm: None,
}
}
@ -294,9 +294,17 @@ impl Schedule {
have_static_call: false,
kill_dust: CleanDustMode::Off,
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 {

View File

@ -76,15 +76,23 @@ pub fn test_finalize(res: Result<GasLeft>) -> Result<U256> {
}
impl FakeExt {
/// New fake externalities
pub fn new() -> Self {
FakeExt::default()
}
/// New fake externalities with byzantium schedule rules
pub fn new_byzantium() -> Self {
let mut ext = FakeExt::default();
ext.schedule = Schedule::new_byzantium();
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 {

View File

@ -68,7 +68,7 @@ impl From<runtime::Error> for vm::Error {
impl vm::Vm for WasmInterpreter {
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)?;
@ -79,8 +79,8 @@ impl vm::Vm for WasmInterpreter {
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolover)
).map_err(Error)?;
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm.opcodes_div) /
U256::from(ext.schedule().wasm.opcodes_mul);
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
U256::from(ext.schedule().wasm().opcodes_mul);
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 ∈ [0..2^64) if static_region ∈ [0..2^16)
// qed
assert!(runtime.schedule().wasm.initial_mem < 1 << 16);
runtime.charge(|s| initial_memory as u64 * s.wasm.initial_mem as u64)?;
assert!(runtime.schedule().wasm().initial_mem < 1 << 16);
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)?;
@ -148,8 +148,8 @@ impl vm::Vm for WasmInterpreter {
};
let gas_left =
U256::from(gas_left) * U256::from(ext.schedule().wasm.opcodes_mul)
/ U256::from(ext.schedule().wasm.opcodes_div);
U256::from(gas_left) * U256::from(ext.schedule().wasm().opcodes_mul)
/ U256::from(ext.schedule().wasm().opcodes_div);
if 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::peek_size;
fn gas_rules(schedule: &vm::Schedule) -> rules::Set {
fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set {
rules::Set::new({
let mut vals = ::std::collections::HashMap::with_capacity(4);
vals.insert(rules::InstructionType::Load, schedule.wasm.mem as u32);
vals.insert(rules::InstructionType::Store, schedule.wasm.mem as u32);
vals.insert(rules::InstructionType::Div, schedule.wasm.div as u32);
vals.insert(rules::InstructionType::Mul, schedule.wasm.mul as u32);
vals.insert(rules::InstructionType::Load, wasm_costs.mem as u32);
vals.insert(rules::InstructionType::Store, wasm_costs.mem as u32);
vals.insert(rules::InstructionType::Div, wasm_costs.div as u32);
vals.insert(rules::InstructionType::Mul, wasm_costs.mul as u32);
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
/// loads the module instance from payload and injects gas counter according
/// 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>
{
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(
deserialized_module,
&gas_rules(schedule),
&gas_rules(wasm_costs),
);
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<()>
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
@ -195,8 +195,8 @@ impl<'a> Runtime<'a> {
{
self.overflow_charge(|schedule|
f(schedule)
.and_then(|x| x.checked_mul(schedule.wasm.opcodes_div as u64))
.map(|x| x / schedule.wasm.opcodes_mul as u64)
.and_then(|x| x.checked_mul(schedule.wasm().opcodes_div 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
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)
.map(|x| x / self.ext.schedule().wasm.opcodes_mul 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)
{
Some(x) => x,
None => {
@ -400,8 +400,8 @@ impl<'a> Runtime<'a> {
vm::MessageCallResult::Success(gas_left, _) => {
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64;
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm().opcodes_mul as u64;
self.memory.set(result_ptr, &result)?;
Ok(0i32.into())
@ -409,8 +409,8 @@ impl<'a> Runtime<'a> {
vm::MessageCallResult::Reverted(gas_left, _) => {
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64;
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm().opcodes_mul as u64;
self.memory.set(result_ptr, &result)?;
Ok((-1i32).into())
@ -438,14 +438,14 @@ impl<'a> Runtime<'a> {
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)?;
Ok(())
}
fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<()> {
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)?;
Ok(())
}
@ -485,8 +485,8 @@ impl<'a> Runtime<'a> {
self.adjusted_charge(|schedule| schedule.create_data_gas as u64 * code.len() as u64)?;
let gas_left: U256 = U256::from(self.gas_left()?)
* U256::from(self.ext.schedule().wasm.opcodes_mul)
/ U256::from(self.ext.schedule().wasm.opcodes_div);
* U256::from(self.ext.schedule().wasm().opcodes_mul)
/ U256::from(self.ext.schedule().wasm().opcodes_div);
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
vm::ContractCreateResult::Created(address, gas_left) => {
@ -494,8 +494,8 @@ impl<'a> Runtime<'a> {
self.gas_counter = self.gas_limit -
// this cannot overflow, since initial gas is in [0..u64::max) range,
// and gas_left cannot be bigger
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64;
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm().opcodes_mul as u64;
trace!(target: "wasm", "runtime: create contract success (@{:?})", address);
Ok(0i32.into())
},
@ -508,8 +508,8 @@ impl<'a> Runtime<'a> {
self.gas_counter = self.gas_limit -
// this cannot overflow, since initial gas is in [0..u64::max) range,
// and gas_left cannot be bigger
gas_left.low_u64() * self.ext.schedule().wasm.opcodes_div as u64
/ self.ext.schedule().wasm.opcodes_mul as u64;
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
/ self.ext.schedule().wasm().opcodes_mul as u64;
Ok((-1i32).into())
},

View File

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

View File

@ -98,8 +98,6 @@ pub struct Params {
pub nonce_cap_increment: Option<Uint>,
/// See `CommonParams` docs.
pub remove_dust_contracts : Option<bool>,
/// Wasm support flag
pub wasm: Option<bool>,
/// See `CommonParams` docs.
#[serde(rename="gasLimitBoundDivisor")]
#[serde(deserialize_with="uint::validate_non_zero")]
@ -118,6 +116,9 @@ pub struct Params {
/// Transaction permission contract address.
#[serde(rename="transactionPermissionContract")]
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)]
@ -137,7 +138,8 @@ mod tests {
"minGasLimit": "0x1388",
"accountStartNonce": "0x01",
"gasLimitBoundDivisor": "0x20",
"maxCodeSize": "0x1000"
"maxCodeSize": "0x1000",
"wasmActivationTransition": "0x1010"
}"#;
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.gas_limit_bound_divisor, Uint(U256::from(0x20)));
assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000))));
assert_eq!(deserialized.wasm_activation_transition, Some(Uint(U256::from(0x1010))));
}
#[test]