|
|
|
@ -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,6 +165,37 @@ 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 { |
|
|
|
@ -177,6 +209,8 @@ type JavascriptTracer struct { |
|
|
|
|
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
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -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,6 +255,7 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) { |
|
|
|
|
mem := &memoryWrapper{} |
|
|
|
|
stack := &stackWrapper{} |
|
|
|
|
db := &dbWrapper{} |
|
|
|
|
contract := &contractWrapper{} |
|
|
|
|
|
|
|
|
|
return &JavascriptTracer{ |
|
|
|
|
vm: vm, |
|
|
|
@ -232,6 +268,8 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) { |
|
|
|
|
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 |
|
|
|
|