Groundwork for basic VM tracing.

This commit is contained in:
Gav Wood 2016-05-27 20:41:29 +02:00
parent 098f9b6ebb
commit 42e4c2d51c
4 changed files with 52 additions and 7 deletions

View File

@ -40,6 +40,9 @@ pub enum MessageCallResult {
Failed
}
/// The trace function callback for VM tracing (*not* transaction tracing - that's different).
pub type VMTraceFunctionBox = Box<FnMut(usize, u8, U256, U256) + Send>;
/// Externalities interface for EVMs
pub trait Ext {
/// Returns a value for given key.
@ -105,4 +108,7 @@ pub trait Ext {
/// Increments sstore refunds count by 1.
fn inc_sstore_clears(&mut self);
/// Provide a tracer for VM tracing if the VM implementation supports it.
fn vm_tracer(&mut self) -> Option<&mut VMTraceFunctionBox>;
}

View File

@ -311,6 +311,12 @@ impl evm::Evm for Interpreter {
);
});
// Call trace
// TODO: allow to be disabled at build time for max speed
if let Some(ref mut trace_instruction) = ext.vm_tracer() {
(*trace_instruction.deref_mut())(reader.position, instruction, gas_cost, current_gas);
}
// Execute instruction
let result = try!(self.exec_instruction(
current_gas, &params, ext, instruction, &mut reader, &mut mem, &mut stack
@ -833,10 +839,12 @@ impl Interpreter {
}
}
fn verify_instructions_requirements(&self,
info: &instructions::InstructionInfo,
stack_limit: usize,
stack: &Stack<U256>) -> Result<(), evm::Error> {
fn verify_instructions_requirements(
&self,
info: &instructions::InstructionInfo,
stack_limit: usize,
stack: &Stack<U256>
) -> Result<(), evm::Error> {
if !stack.has(info.args) {
Err(evm::Error::StackUnderflow {
instruction: info.name,

View File

@ -30,6 +30,6 @@ mod jit;
mod tests;
pub use self::evm::{Evm, Error, Result};
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult};
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, VMTraceFunctionBox};
pub use self::factory::{Factory, VMType};
pub use self::schedule::Schedule;

View File

@ -19,7 +19,7 @@ use common::*;
use state::*;
use engine::*;
use executive::*;
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory};
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory, VMTraceFunctionBox};
use substate::*;
use trace::Tracer;
@ -66,10 +66,10 @@ pub struct Externalities<'a, T> where T: 'a + Tracer {
schedule: Schedule,
output: OutputPolicy<'a, 'a>,
tracer: &'a mut T,
vm_tracer: Option<VMTraceFunctionBox>,
}
impl<'a, T> Externalities<'a, T> where T: 'a + Tracer {
#[cfg_attr(feature="dev", allow(too_many_arguments))]
/// Basic `Externalities` constructor.
pub fn new(state: &'a mut State,
@ -93,6 +93,35 @@ impl<'a, T> Externalities<'a, T> where T: 'a + Tracer {
schedule: engine.schedule(env_info),
output: output,
tracer: tracer,
vm_tracer: None,
}
}
#[cfg_attr(feature="dev", allow(too_many_arguments))]
/// Basic `Externalities` constructor.
pub fn with_vm_tracer(state: &'a mut State,
env_info: &'a EnvInfo,
engine: &'a Engine,
vm_factory: &'a Factory,
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy<'a, 'a>,
tracer: &'a mut T,
vm_tracer: VMTraceFunctionBox,
) -> Self {
Externalities {
state: state,
env_info: env_info,
engine: engine,
vm_factory: vm_factory,
depth: depth,
origin_info: origin_info,
substate: substate,
schedule: engine.schedule(env_info),
output: output,
tracer: tracer,
vm_tracer: Some(vm_tracer),
}
}
}
@ -286,6 +315,8 @@ impl<'a, T> Ext for Externalities<'a, T> where T: 'a + Tracer {
fn inc_sstore_clears(&mut self) {
self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one();
}
fn vm_tracer(&mut self) -> Option<&mut VMTraceFunctionBox> { self.vm_tracer.as_mut() }
}
#[cfg(test)]