aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--internal/ethapi/tracer.go85
1 files changed, 42 insertions, 43 deletions
diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go
index fc742e6c4..71cafc6e9 100644
--- a/internal/ethapi/tracer.go
+++ b/internal/ethapi/tracer.go
@@ -200,19 +200,18 @@ func (c *contractWrapper) toValue(vm *otto.Otto) otto.Value {
// JavascriptTracer provides an implementation of Tracer that evaluates a
// Javascript function for each VM execution step.
type JavascriptTracer struct {
- vm *otto.Otto // Javascript VM instance
- traceobj *otto.Object // User-supplied object to call
- log map[string]interface{} // (Reusable) map for the `log` arg to `step`
- logvalue otto.Value // JS view of `log`
- memory *memoryWrapper // Wrapper around the VM memory
- memvalue otto.Value // JS view of `memory`
- stack *stackWrapper // Wrapper around the VM stack
- stackvalue otto.Value // JS view of `stack`
- db *dbWrapper // Wrapper around the VM environment
- dbvalue otto.Value // JS view of `db`
- contract *contractWrapper // Wrapper around the contract object
- contractvalue otto.Value // JS view of `contract`
- err error // Error, if one has occurred
+ vm *otto.Otto // Javascript VM instance
+ traceobj *otto.Object // User-supplied object to call
+ op *opCodeWrapper // Wrapper around the VM opcode
+ log map[string]interface{} // (Reusable) map for the `log` arg to `step`
+ logvalue otto.Value // JS view of `log`
+ memory *memoryWrapper // Wrapper around the VM memory
+ stack *stackWrapper // Wrapper around the VM stack
+ db *dbWrapper // Wrapper around the VM environment
+ dbvalue otto.Value // JS view of `db`
+ contract *contractWrapper // Wrapper around the contract object
+ err error // Error, if one has occurred
+ result interface{} // Final result to return to the user
}
// NewJavascriptTracer instantiates a new JavascriptTracer instance.
@@ -230,7 +229,6 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
if err != nil {
return nil, err
}
-
// Check the required functions exist
step, err := jstracer.Get("step")
if err != nil {
@@ -247,31 +245,34 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
if !result.IsFunction() {
return nil, fmt.Errorf("Trace object must expose a function result()")
}
-
// Create the persistent log object
- log := make(map[string]interface{})
+ var (
+ op = new(opCodeWrapper)
+ mem = new(memoryWrapper)
+ stack = new(stackWrapper)
+ db = new(dbWrapper)
+ contract = new(contractWrapper)
+ )
+ log := map[string]interface{}{
+ "op": op.toValue(vm),
+ "memory": mem.toValue(vm),
+ "stack": stack.toValue(vm),
+ "contract": contract.toValue(vm),
+ }
logvalue, _ := vm.ToValue(log)
- // Create persistent wrappers for memory and stack
- mem := &memoryWrapper{}
- stack := &stackWrapper{}
- db := &dbWrapper{}
- contract := &contractWrapper{}
-
return &JavascriptTracer{
- vm: vm,
- traceobj: jstracer,
- log: log,
- logvalue: logvalue,
- memory: mem,
- memvalue: mem.toValue(vm),
- stack: stack,
- stackvalue: stack.toValue(vm),
- db: db,
- dbvalue: db.toValue(vm),
- contract: contract,
- contractvalue: contract.toValue(vm),
- err: nil,
+ vm: vm,
+ traceobj: jstracer,
+ op: op,
+ log: log,
+ logvalue: logvalue,
+ memory: mem,
+ stack: stack,
+ db: db,
+ dbvalue: db.toValue(vm),
+ contract: contract,
+ err: nil,
}, nil
}
@@ -319,24 +320,22 @@ func wrapError(context string, err error) error {
// CaptureState implements the Tracer interface to trace a single step of VM execution
func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
if jst.err == nil {
+ jst.op.op = op
jst.memory.memory = memory
jst.stack.stack = stack
jst.db.db = env.StateDB
jst.contract.contract = contract
- ocw := &opCodeWrapper{op}
-
jst.log["pc"] = pc
- jst.log["op"] = ocw.toValue(jst.vm)
jst.log["gas"] = gas
- jst.log["gasPrice"] = cost
- jst.log["memory"] = jst.memvalue
- jst.log["stack"] = jst.stackvalue
- jst.log["contract"] = jst.contractvalue
+ jst.log["cost"] = cost
jst.log["depth"] = depth
jst.log["account"] = contract.Address()
- jst.log["err"] = err
+ delete(jst.log, "error")
+ if err != nil {
+ jst.log["error"] = err
+ }
_, err := jst.callSafely("step", jst.logvalue, jst.dbvalue)
if err != nil {
jst.err = wrapError("step", err)