Decouple virtual machines (#6184)
* work in progress for splitting vms * evm working * Evm -> Vm * wasm converted * ethcore working * test fixes
This commit is contained in:
@@ -17,15 +17,15 @@
|
||||
use util::*;
|
||||
use super::u256_to_address;
|
||||
|
||||
use {evm, ext};
|
||||
use {evm, vm};
|
||||
use instructions::{self, Instruction, InstructionInfo};
|
||||
use interpreter::stack::Stack;
|
||||
use schedule::Schedule;
|
||||
use vm::Schedule;
|
||||
|
||||
macro_rules! overflowing {
|
||||
($x: expr) => {{
|
||||
let (v, overflow) = $x;
|
||||
if overflow { return Err(evm::Error::OutOfGas); }
|
||||
if overflow { return Err(vm::Error::OutOfGas); }
|
||||
v
|
||||
}}
|
||||
}
|
||||
@@ -59,16 +59,16 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_gas(&self, gas_cost: &Gas) -> evm::Result<()> {
|
||||
pub fn verify_gas(&self, gas_cost: &Gas) -> vm::Result<()> {
|
||||
match &self.current_gas < gas_cost {
|
||||
true => Err(evm::Error::OutOfGas),
|
||||
true => Err(vm::Error::OutOfGas),
|
||||
false => Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
|
||||
/// and that we `requested` some.
|
||||
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> evm::Result<Gas> {
|
||||
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> vm::Result<Gas> {
|
||||
// Try converting requested gas to `Gas` (`U256/u64`)
|
||||
// but in EIP150 even if we request more we should never fail from OOG
|
||||
let requested = requested.map(Gas::from_u256);
|
||||
@@ -107,12 +107,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
/// it will be the amount of gas that the current context provides to the child context.
|
||||
pub fn requirements(
|
||||
&mut self,
|
||||
ext: &ext::Ext,
|
||||
ext: &vm::Ext,
|
||||
instruction: Instruction,
|
||||
info: &InstructionInfo,
|
||||
stack: &Stack<U256>,
|
||||
current_mem_size: usize,
|
||||
) -> evm::Result<InstructionRequirements<Gas>> {
|
||||
) -> vm::Result<InstructionRequirements<Gas>> {
|
||||
let schedule = ext.schedule();
|
||||
let tier = instructions::get_tier_idx(info.tier);
|
||||
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
|
||||
@@ -291,7 +291,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
})
|
||||
}
|
||||
|
||||
fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> {
|
||||
fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> vm::Result<(Gas, Gas, usize)> {
|
||||
let gas_for_mem = |mem_size: Gas| {
|
||||
let s = mem_size >> 5;
|
||||
// s * memory_gas + s * s / quad_coeff_div
|
||||
@@ -319,12 +319,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
|
||||
|
||||
#[inline]
|
||||
fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> evm::Result<Gas> {
|
||||
fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> vm::Result<Gas> {
|
||||
Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add))))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> {
|
||||
fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> vm::Result<Gas> {
|
||||
if size.is_zero() {
|
||||
return Ok(Gas::from(0));
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::U256;
|
||||
use {ReturnData};
|
||||
use vm::ReturnData;
|
||||
|
||||
const MAX_RETURN_WASTE_BYTES: usize = 16384;
|
||||
|
||||
|
||||
@@ -23,17 +23,21 @@ mod stack;
|
||||
mod memory;
|
||||
mod shared_cache;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use vm::{
|
||||
self, ActionParams, ActionValue, CallType, MessageCallResult,
|
||||
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft
|
||||
};
|
||||
|
||||
use evm::CostType;
|
||||
use instructions::{self, Instruction, InstructionInfo};
|
||||
|
||||
use self::gasometer::Gasometer;
|
||||
use self::stack::{Stack, VecStack};
|
||||
use self::memory::Memory;
|
||||
pub use self::shared_cache::SharedCache;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use action_params::{ActionParams, ActionValue};
|
||||
use call_type::CallType;
|
||||
use instructions::{self, Instruction, InstructionInfo};
|
||||
use evm::{self, GasLeft, CostType, ReturnData};
|
||||
use ext::{self, MessageCallResult, ContractCreateResult, CreateContractAddress};
|
||||
use bit_set::BitSet;
|
||||
|
||||
use util::*;
|
||||
@@ -107,8 +111,8 @@ pub struct Interpreter<Cost: CostType> {
|
||||
_type: PhantomData<Cost>,
|
||||
}
|
||||
|
||||
impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
||||
fn exec(&mut self, params: ActionParams, ext: &mut ext::Ext) -> evm::Result<GasLeft> {
|
||||
impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
|
||||
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||
self.mem.clear();
|
||||
|
||||
let mut informant = informant::EvmInformant::new(ext.depth());
|
||||
@@ -205,7 +209,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_instruction(&self, ext: &ext::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
|
||||
fn verify_instruction(&self, ext: &vm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> vm::Result<()> {
|
||||
let schedule = ext.schedule();
|
||||
|
||||
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
|
||||
@@ -214,25 +218,25 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) ||
|
||||
(instruction == instructions::REVERT && !schedule.have_revert) {
|
||||
|
||||
return Err(evm::Error::BadInstruction {
|
||||
return Err(vm::Error::BadInstruction {
|
||||
instruction: instruction
|
||||
});
|
||||
}
|
||||
|
||||
if info.tier == instructions::GasPriceTier::Invalid {
|
||||
return Err(evm::Error::BadInstruction {
|
||||
return Err(vm::Error::BadInstruction {
|
||||
instruction: instruction
|
||||
});
|
||||
}
|
||||
|
||||
if !stack.has(info.args) {
|
||||
Err(evm::Error::StackUnderflow {
|
||||
Err(vm::Error::StackUnderflow {
|
||||
instruction: info.name,
|
||||
wanted: info.args,
|
||||
on_stack: stack.size()
|
||||
})
|
||||
} else if stack.size() - info.args + info.ret > schedule.stack_limit {
|
||||
Err(evm::Error::OutOfStack {
|
||||
Err(vm::Error::OutOfStack {
|
||||
instruction: info.name,
|
||||
wanted: info.ret - info.args,
|
||||
limit: schedule.stack_limit
|
||||
@@ -272,12 +276,12 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
&mut self,
|
||||
gas: Cost,
|
||||
params: &ActionParams,
|
||||
ext: &mut ext::Ext,
|
||||
ext: &mut vm::Ext,
|
||||
instruction: Instruction,
|
||||
code: &mut CodeReader,
|
||||
stack: &mut Stack<U256>,
|
||||
provided: Option<Cost>
|
||||
) -> evm::Result<InstructionResult<Cost>> {
|
||||
) -> vm::Result<InstructionResult<Cost>> {
|
||||
match instruction {
|
||||
instructions::JUMP => {
|
||||
let jump = stack.pop_back();
|
||||
@@ -593,13 +597,13 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> evm::Result<usize> {
|
||||
fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> vm::Result<usize> {
|
||||
let jump = jump_u.low_u64() as usize;
|
||||
|
||||
if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u {
|
||||
Ok(jump)
|
||||
} else {
|
||||
Err(evm::Error::BadJumpDestination {
|
||||
Err(vm::Error::BadJumpDestination {
|
||||
destination: jump
|
||||
})
|
||||
}
|
||||
@@ -617,7 +621,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> evm::Result<()> {
|
||||
fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack<U256>) -> vm::Result<()> {
|
||||
match instruction {
|
||||
instructions::DUP1...instructions::DUP16 => {
|
||||
let position = instructions::get_dup_position(instruction);
|
||||
@@ -822,7 +826,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(evm::Error::BadInstruction {
|
||||
return Err(vm::Error::BadInstruction {
|
||||
instruction: instruction
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user