internal/ethapi: Add support for fetching information about the current call in JS traces
This commit is contained in:
		@@ -23,6 +23,7 @@ import (
 | 
				
			|||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/vm"
 | 
						"github.com/ethereum/go-ethereum/core/vm"
 | 
				
			||||||
	"github.com/robertkrimen/otto"
 | 
						"github.com/robertkrimen/otto"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -164,20 +165,53 @@ func (dw *dbWrapper) toValue(vm *otto.Otto) otto.Value {
 | 
				
			|||||||
	return 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
 | 
					// JavascriptTracer provides an implementation of Tracer that evaluates a
 | 
				
			||||||
// Javascript function for each VM execution step.
 | 
					// Javascript function for each VM execution step.
 | 
				
			||||||
type JavascriptTracer struct {
 | 
					type JavascriptTracer struct {
 | 
				
			||||||
	vm         *otto.Otto             // Javascript VM instance
 | 
						vm            *otto.Otto             // Javascript VM instance
 | 
				
			||||||
	traceobj   *otto.Object           // User-supplied object to call
 | 
						traceobj      *otto.Object           // User-supplied object to call
 | 
				
			||||||
	log        map[string]interface{} // (Reusable) map for the `log` arg to `step`
 | 
						log           map[string]interface{} // (Reusable) map for the `log` arg to `step`
 | 
				
			||||||
	logvalue   otto.Value             // JS view of `log`
 | 
						logvalue      otto.Value             // JS view of `log`
 | 
				
			||||||
	memory     *memoryWrapper         // Wrapper around the VM memory
 | 
						memory        *memoryWrapper         // Wrapper around the VM memory
 | 
				
			||||||
	memvalue   otto.Value             // JS view of `memory`
 | 
						memvalue      otto.Value             // JS view of `memory`
 | 
				
			||||||
	stack      *stackWrapper          // Wrapper around the VM stack
 | 
						stack         *stackWrapper          // Wrapper around the VM stack
 | 
				
			||||||
	stackvalue otto.Value             // JS view of `stack`
 | 
						stackvalue    otto.Value             // JS view of `stack`
 | 
				
			||||||
	db         *dbWrapper             // Wrapper around the VM environment
 | 
						db            *dbWrapper             // Wrapper around the VM environment
 | 
				
			||||||
	dbvalue    otto.Value             // JS view of `db`
 | 
						dbvalue       otto.Value             // JS view of `db`
 | 
				
			||||||
	err        error                  // Error, if one has occurred
 | 
						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.
 | 
					// NewJavascriptTracer instantiates a new JavascriptTracer instance.
 | 
				
			||||||
@@ -189,6 +223,7 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Set up builtins for this environment
 | 
						// Set up builtins for this environment
 | 
				
			||||||
	vm.Set("big", &fakeBig{})
 | 
						vm.Set("big", &fakeBig{})
 | 
				
			||||||
 | 
						vm.Set("toHex", hexutil.Encode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jstracer, err := vm.Object("(" + code + ")")
 | 
						jstracer, err := vm.Object("(" + code + ")")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -220,19 +255,22 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) {
 | 
				
			|||||||
	mem := &memoryWrapper{}
 | 
						mem := &memoryWrapper{}
 | 
				
			||||||
	stack := &stackWrapper{}
 | 
						stack := &stackWrapper{}
 | 
				
			||||||
	db := &dbWrapper{}
 | 
						db := &dbWrapper{}
 | 
				
			||||||
 | 
						contract := &contractWrapper{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &JavascriptTracer{
 | 
						return &JavascriptTracer{
 | 
				
			||||||
		vm:         vm,
 | 
							vm:            vm,
 | 
				
			||||||
		traceobj:   jstracer,
 | 
							traceobj:      jstracer,
 | 
				
			||||||
		log:        log,
 | 
							log:           log,
 | 
				
			||||||
		logvalue:   logvalue,
 | 
							logvalue:      logvalue,
 | 
				
			||||||
		memory:     mem,
 | 
							memory:        mem,
 | 
				
			||||||
		memvalue:   mem.toValue(vm),
 | 
							memvalue:      mem.toValue(vm),
 | 
				
			||||||
		stack:      stack,
 | 
							stack:         stack,
 | 
				
			||||||
		stackvalue: stack.toValue(vm),
 | 
							stackvalue:    stack.toValue(vm),
 | 
				
			||||||
		db:         db,
 | 
							db:            db,
 | 
				
			||||||
		dbvalue:    db.toValue(vm),
 | 
							dbvalue:       db.toValue(vm),
 | 
				
			||||||
		err:        nil,
 | 
							contract:      contract,
 | 
				
			||||||
 | 
							contractvalue: contract.toValue(vm),
 | 
				
			||||||
 | 
							err:           nil,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -283,6 +321,7 @@ func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
 | 
				
			|||||||
		jst.memory.memory = memory
 | 
							jst.memory.memory = memory
 | 
				
			||||||
		jst.stack.stack = stack
 | 
							jst.stack.stack = stack
 | 
				
			||||||
		jst.db.db = env.StateDB
 | 
							jst.db.db = env.StateDB
 | 
				
			||||||
 | 
							jst.contract.contract = contract
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ocw := &opCodeWrapper{op}
 | 
							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["gasPrice"] = cost
 | 
				
			||||||
		jst.log["memory"] = jst.memvalue
 | 
							jst.log["memory"] = jst.memvalue
 | 
				
			||||||
		jst.log["stack"] = jst.stackvalue
 | 
							jst.log["stack"] = jst.stackvalue
 | 
				
			||||||
 | 
							jst.log["contract"] = jst.contractvalue
 | 
				
			||||||
		jst.log["depth"] = depth
 | 
							jst.log["depth"] = depth
 | 
				
			||||||
		jst.log["account"] = contract.Address()
 | 
							jst.log["account"] = contract.Address()
 | 
				
			||||||
		jst.log["err"] = err
 | 
							jst.log["err"] = err
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user