@ -142,19 +142,29 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracer
vm : vm ,
vm : vm ,
ctx : make ( map [ string ] goja . Value ) ,
ctx : make ( map [ string ] goja . Value ) ,
}
}
t . setTypeConverters ( )
t . setBuiltinFunctions ( )
if ctx == nil {
if ctx == nil {
ctx = new ( tracers . Context )
ctx = new ( tracers . Context )
}
}
if ctx . BlockHash != ( common . Hash { } ) {
if ctx . BlockHash != ( common . Hash { } ) {
t . ctx [ "blockHash" ] = vm . ToValue ( ctx . BlockHash . Bytes ( ) )
blockHash , err := t . toBuf ( vm , ctx . BlockHash . Bytes ( ) )
if err != nil {
return nil , err
}
t . ctx [ "blockHash" ] = blockHash
if ctx . TxHash != ( common . Hash { } ) {
if ctx . TxHash != ( common . Hash { } ) {
t . ctx [ "txIndex" ] = vm . ToValue ( ctx . TxIndex )
t . ctx [ "txIndex" ] = vm . ToValue ( ctx . TxIndex )
t . ctx [ "txHash" ] = vm . ToValue ( ctx . TxHash . Bytes ( ) )
txHash , err := t . toBuf ( vm , ctx . TxHash . Bytes ( ) )
if err != nil {
return nil , err
}
t . ctx [ "txHash" ] = txHash
}
}
}
}
t . setTypeConverters ( )
t . setBuiltinFunctions ( )
ret , err := vm . RunString ( "(" + code + ")" )
ret , err := vm . RunString ( "(" + code + ")" )
if err != nil {
if err != nil {
return nil , err
return nil , err
@ -224,6 +234,10 @@ func (t *jsTracer) CaptureTxEnd(restGas uint64) {
// CaptureStart implements the Tracer interface to initialize the tracing operation.
// CaptureStart implements the Tracer interface to initialize the tracing operation.
func ( t * jsTracer ) CaptureStart ( env * vm . EVM , from common . Address , to common . Address , create bool , input [ ] byte , gas uint64 , value * big . Int ) {
func ( t * jsTracer ) CaptureStart ( env * vm . EVM , from common . Address , to common . Address , create bool , input [ ] byte , gas uint64 , value * big . Int ) {
cancel := func ( err error ) {
t . err = err
t . env . Cancel ( )
}
t . env = env
t . env = env
db := & dbObj { db : env . StateDB , vm : t . vm , toBig : t . toBig , toBuf : t . toBuf , fromBuf : t . fromBuf }
db := & dbObj { db : env . StateDB , vm : t . vm , toBig : t . toBig , toBuf : t . toBuf , fromBuf : t . fromBuf }
t . dbValue = db . setupObject ( )
t . dbValue = db . setupObject ( )
@ -232,19 +246,34 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
} else {
} else {
t . ctx [ "type" ] = t . vm . ToValue ( "CALL" )
t . ctx [ "type" ] = t . vm . ToValue ( "CALL" )
}
}
t . ctx [ "from" ] = t . vm . ToValue ( from . Bytes ( ) )
fromVal , err := t . toBuf ( t . vm , from . Bytes ( ) )
t . ctx [ "to" ] = t . vm . ToValue ( to . Bytes ( ) )
if err != nil {
t . ctx [ "input" ] = t . vm . ToValue ( input )
cancel ( err )
return
}
t . ctx [ "from" ] = fromVal
toVal , err := t . toBuf ( t . vm , to . Bytes ( ) )
if err != nil {
cancel ( err )
return
}
t . ctx [ "to" ] = toVal
inputVal , err := t . toBuf ( t . vm , input )
if err != nil {
cancel ( err )
return
}
t . ctx [ "input" ] = inputVal
t . ctx [ "gas" ] = t . vm . ToValue ( t . gasLimit )
t . ctx [ "gas" ] = t . vm . ToValue ( t . gasLimit )
gasPriceBig , err := t . toBig ( t . vm , env . TxContext . GasPrice . String ( ) )
gasPriceBig , err := t . toBig ( t . vm , env . TxContext . GasPrice . String ( ) )
if err != nil {
if err != nil {
t . err = err
cancel ( err )
return
return
}
}
t . ctx [ "gasPrice" ] = gasPriceBig
t . ctx [ "gasPrice" ] = gasPriceBig
valueBig , err := t . toBig ( t . vm , value . String ( ) )
valueBig , err := t . toBig ( t . vm , value . String ( ) )
if err != nil {
if err != nil {
t . err = err
cancel ( err )
return
return
}
}
t . ctx [ "value" ] = valueBig
t . ctx [ "value" ] = valueBig
@ -293,10 +322,15 @@ func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope
// CaptureEnd is called after the call finishes to finalize the tracing.
// CaptureEnd is called after the call finishes to finalize the tracing.
func ( t * jsTracer ) CaptureEnd ( output [ ] byte , gasUsed uint64 , err error ) {
func ( t * jsTracer ) CaptureEnd ( output [ ] byte , gasUsed uint64 , err error ) {
t . ctx [ "output" ] = t . vm . ToValue ( output )
if err != nil {
if err != nil {
t . ctx [ "error" ] = t . vm . ToValue ( err . Error ( ) )
t . ctx [ "error" ] = t . vm . ToValue ( err . Error ( ) )
}
}
outputVal , err := t . toBuf ( t . vm , output )
if err != nil {
t . err = err
return
}
t . ctx [ "output" ] = outputVal
}
}
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
@ -465,13 +499,13 @@ func (t *jsTracer) setBuiltinFunctions() {
}
}
return false
return false
} )
} )
vm . Set ( "slice" , func ( slice goja . Value , start , end int ) goja . Value {
vm . Set ( "slice" , func ( slice goja . Value , start , end int64 ) goja . Value {
b , err := t . fromBuf ( vm , slice , false )
b , err := t . fromBuf ( vm , slice , false )
if err != nil {
if err != nil {
vm . Interrupt ( err )
vm . Interrupt ( err )
return nil
return nil
}
}
if start < 0 || start > end || end > len ( b ) {
if start < 0 || start > end || end > int64 ( len ( b ) ) {
vm . Interrupt ( fmt . Sprintf ( "Tracer accessed out of bound memory: available %d, offset %d, size %d" , len ( b ) , start , end - start ) )
vm . Interrupt ( fmt . Sprintf ( "Tracer accessed out of bound memory: available %d, offset %d, size %d" , len ( b ) , start , end - start ) )
return nil
return nil
}
}