aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Johnson <arachnid@notdot.net>2017-04-11 18:37:23 +0800
committerNick Johnson <arachnid@notdot.net>2017-04-11 18:37:23 +0800
commit49f1e84253e9c7923cf0904bb01a37a3218ee956 (patch)
tree8bde28fb3e8d41dc4592d89e5760a1ead0fe8f86
parentcc13d576f07fb6803e09fb42880591a67b8b0ef6 (diff)
downloaddexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar.gz
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar.bz2
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar.lz
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar.xz
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.tar.zst
dexon-49f1e84253e9c7923cf0904bb01a37a3218ee956.zip
internal/ethapi: Add support for fetching information about the current call in JS traces
-rw-r--r--internal/ethapi/tracer.go84
1 files changed, 62 insertions, 22 deletions
diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go
index fe2685375..d34363564 100644
--- a/internal/ethapi/tracer.go
+++ b/internal/ethapi/tracer.go
@@ -23,6 +23,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/robertkrimen/otto"
)
@@ -164,20 +165,53 @@ func (dw *dbWrapper) toValue(vm *otto.Otto) otto.Value {
return value
}
+// contractWrapper provides a JS wrapper around vm.Contract
+type contractWrapper struct {
+ contract *vm.Contract
+}
+
+func (c *contractWrapper) caller() common.Address {
+ return c.contract.Caller()
+}
+
+func (c *contractWrapper) address() common.Address {
+ return c.contract.Address()
+}
+
+func (c *contractWrapper) value() *big.Int {
+ return c.contract.Value()
+}
+
+func (c *contractWrapper) calldata() []byte {
+ return c.contract.Input
+}
+
+func (c *contractWrapper) toValue(vm *otto.Otto) otto.Value {
+ value, _ := vm.ToValue(c)
+ obj := value.Object()
+ obj.Set("caller", c.caller)
+ obj.Set("address", c.address)
+ obj.Set("value", c.value)
+ obj.Set("calldata", c.calldata)
+ return 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`
- err error // Error, if one has occurred
+ 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
}
// NewJavascriptTracer instantiates a new JavascriptTracer instance.
@@ -189,6 +223,7 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
// Set up builtins for this environment
vm.Set("big", &fakeBig{})
+ vm.Set("toHex", hexutil.Encode)
jstracer, err := vm.Object("(" + code + ")")
if err != nil {
@@ -220,19 +255,22 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
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),
- err: nil,
+ 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,
}, nil
}
@@ -283,6 +321,7 @@ func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
jst.memory.memory = memory
jst.stack.stack = stack
jst.db.db = env.StateDB
+ jst.contract.contract = contract
ocw := &opCodeWrapper{op}
@@ -292,6 +331,7 @@ func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
jst.log["gasPrice"] = cost
jst.log["memory"] = jst.memvalue
jst.log["stack"] = jst.stackvalue
+ jst.log["contract"] = jst.contractvalue
jst.log["depth"] = depth
jst.log["account"] = contract.Address()
jst.log["err"] = err