mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Merge branch 'extended-tracer-backport-1.13.5' into extended-tracer-sei
This commit is contained in:
commit
9beae74e50
17 changed files with 205 additions and 34 deletions
|
|
@ -60,7 +60,7 @@ func blockTestCmd(ctx *cli.Context) error {
|
||||||
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||||
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
||||||
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
||||||
}, os.Stderr).Hooks()
|
}, os.Stderr)
|
||||||
}
|
}
|
||||||
// Load the test content from the input file
|
// Load the test content from the input file
|
||||||
src, err := os.ReadFile(ctx.Args().First())
|
src, err := os.ReadFile(ctx.Args().First())
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
if vmConfig.Tracer != nil {
|
if tracer != nil {
|
||||||
vmConfig.Tracer = tracer.Hooks
|
vmConfig.Tracer = tracer.Hooks
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), txIndex)
|
statedb.SetTxContext(tx.Hash(), txIndex)
|
||||||
|
|
@ -240,7 +240,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
)
|
)
|
||||||
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
|
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
|
||||||
|
|
||||||
if tracer != nil {
|
if tracer != nil && tracer.OnTxStart != nil {
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}
|
}
|
||||||
// (ret []byte, usedGas uint64, failed bool, err error)
|
// (ret []byte, usedGas uint64, failed bool, err error)
|
||||||
|
|
@ -251,7 +251,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
||||||
gaspool.SetGas(prevGas)
|
gaspool.SetGas(prevGas)
|
||||||
if tracer != nil {
|
if tracer != nil {
|
||||||
|
if tracer.OnTxEnd != nil {
|
||||||
tracer.OnTxEnd(nil, err)
|
tracer.OnTxEnd(nil, err)
|
||||||
|
}
|
||||||
if err := writeTraceResult(tracer, traceOutput); err != nil {
|
if err := writeTraceResult(tracer, traceOutput); err != nil {
|
||||||
log.Warn("Error writing tracer output", "err", err)
|
log.Warn("Error writing tracer output", "err", err)
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +300,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
receipt.TransactionIndex = uint(txIndex)
|
receipt.TransactionIndex = uint(txIndex)
|
||||||
receipts = append(receipts, receipt)
|
receipts = append(receipts, receipt)
|
||||||
if tracer != nil {
|
if tracer != nil {
|
||||||
|
if tracer.Hooks.OnTxEnd != nil {
|
||||||
tracer.Hooks.OnTxEnd(receipt, nil)
|
tracer.Hooks.OnTxEnd(receipt, nil)
|
||||||
|
}
|
||||||
writeTraceResult(tracer, traceOutput)
|
writeTraceResult(tracer, traceOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -418,7 +422,7 @@ func calcDifficulty(config *params.ChainConfig, number, currentTime, parentTime
|
||||||
func writeTraceResult(tracer *directory.Tracer, f io.WriteCloser) error {
|
func writeTraceResult(tracer *directory.Tracer, f io.WriteCloser) error {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
result, err := tracer.GetResult()
|
result, err := tracer.GetResult()
|
||||||
if err != nil {
|
if err != nil || result == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = json.NewEncoder(f).Encode(result)
|
err = json.NewEncoder(f).Encode(result)
|
||||||
|
|
|
||||||
|
|
@ -126,10 +126,10 @@ func Transition(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
}
|
}
|
||||||
logger := logger.NewJSONLogger(logConfig, traceFile).Hooks()
|
logger := logger.NewJSONLogger(logConfig, traceFile)
|
||||||
tracer := &directory.Tracer{
|
tracer := &directory.Tracer{
|
||||||
Hooks: logger,
|
Hooks: logger,
|
||||||
// JSONLogger streams out result to file.
|
// jsonLogger streams out result to file.
|
||||||
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
||||||
Stop: func(err error) {},
|
Stop: func(err error) {},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
|
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
|
||||||
)
|
)
|
||||||
if ctx.Bool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
tracer = logger.NewJSONLogger(logconfig, os.Stdout).Hooks()
|
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
||||||
} else if ctx.Bool(DebugFlag.Name) {
|
} else if ctx.Bool(DebugFlag.Name) {
|
||||||
debugLogger = logger.NewStructLogger(logconfig)
|
debugLogger = logger.NewStructLogger(logconfig)
|
||||||
tracer = debugLogger.Hooks()
|
tracer = debugLogger.Hooks()
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
var cfg vm.Config
|
var cfg vm.Config
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(MachineFlag.Name):
|
case ctx.Bool(MachineFlag.Name):
|
||||||
cfg.Tracer = logger.NewJSONLogger(config, os.Stderr).Hooks()
|
cfg.Tracer = logger.NewJSONLogger(config, os.Stderr)
|
||||||
|
|
||||||
case ctx.Bool(DebugFlag.Name):
|
case ctx.Bool(DebugFlag.Name):
|
||||||
cfg.Tracer = logger.NewStructLogger(config).Hooks()
|
cfg.Tracer = logger.NewStructLogger(config).Hooks()
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -321,6 +324,107 @@ func TestT8n(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lineIterator(path string) func() (string, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return func() (string, error) { return err.Error(), err }
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(strings.NewReader(string(data)))
|
||||||
|
return func() (string, error) {
|
||||||
|
if scanner.Scan() {
|
||||||
|
return scanner.Text(), nil
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "", io.EOF // scanner gobbles io.EOF, but we want it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestT8nTracing is a test that checks the tracing-output from t8n.
|
||||||
|
func TestT8nTracing(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tt := new(testT8n)
|
||||||
|
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
|
||||||
|
for i, tc := range []struct {
|
||||||
|
base string
|
||||||
|
input t8nInput
|
||||||
|
expExitCode int
|
||||||
|
extraArgs []string
|
||||||
|
expectedTraces []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
base: "./testdata/31",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs.json", "env.json", "Cancun", "",
|
||||||
|
},
|
||||||
|
extraArgs: []string{"--trace"},
|
||||||
|
expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.jsonl"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base: "./testdata/31",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs.json", "env.json", "Cancun", "",
|
||||||
|
},
|
||||||
|
extraArgs: []string{"--trace.tracer", `
|
||||||
|
{
|
||||||
|
result: function(){
|
||||||
|
return "hello world"
|
||||||
|
},
|
||||||
|
fault: function(){}
|
||||||
|
}`},
|
||||||
|
expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
args := []string{"t8n"}
|
||||||
|
args = append(args, tc.input.get(tc.base)...)
|
||||||
|
// Place the output somewhere we can find it
|
||||||
|
outdir := t.TempDir()
|
||||||
|
args = append(args, "--output.basedir", outdir)
|
||||||
|
args = append(args, tc.extraArgs...)
|
||||||
|
|
||||||
|
var qArgs []string // quoted args for debugging purposes
|
||||||
|
for _, arg := range args {
|
||||||
|
if len(arg) == 0 {
|
||||||
|
qArgs = append(qArgs, `""`)
|
||||||
|
} else {
|
||||||
|
qArgs = append(qArgs, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tt.Logf("args: %v\n", strings.Join(qArgs, " "))
|
||||||
|
tt.Run("evm-test", args...)
|
||||||
|
t.Log(string(tt.Output()))
|
||||||
|
|
||||||
|
// Compare the expected traces
|
||||||
|
for _, traceFile := range tc.expectedTraces {
|
||||||
|
haveFn := lineIterator(filepath.Join(outdir, traceFile))
|
||||||
|
wantFn := lineIterator(filepath.Join(tc.base, traceFile))
|
||||||
|
|
||||||
|
for line := 0; ; line++ {
|
||||||
|
want, wErr := wantFn()
|
||||||
|
have, hErr := haveFn()
|
||||||
|
if want != have {
|
||||||
|
t.Fatalf("test %d, trace %v, line %d\nwant: %v\nhave: %v\n",
|
||||||
|
i, traceFile, line, want, have)
|
||||||
|
}
|
||||||
|
if wErr != nil && hErr != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if wErr != nil {
|
||||||
|
t.Fatal(wErr)
|
||||||
|
}
|
||||||
|
if hErr != nil {
|
||||||
|
t.Fatal(hErr)
|
||||||
|
}
|
||||||
|
t.Logf("%v\n", want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if have, want := tt.ExitStatus(), tc.expExitCode; have != want {
|
||||||
|
t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type t9nInput struct {
|
type t9nInput struct {
|
||||||
inTxs string
|
inTxs string
|
||||||
stFork string
|
stFork string
|
||||||
|
|
|
||||||
1
cmd/evm/testdata/31/README.md
vendored
Normal file
1
cmd/evm/testdata/31/README.md
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
This test does some EVM execution, and can be used to test the tracers and trace-outputs.
|
||||||
16
cmd/evm/testdata/31/alloc.json
vendored
Normal file
16
cmd/evm/testdata/31/alloc.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x016345785d8a0000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0x1111111111111111111111111111111111111111" : {
|
||||||
|
"balance" : "0x1",
|
||||||
|
"code" : "0x604060406040604000",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
cmd/evm/testdata/31/env.json
vendored
Normal file
20
cmd/evm/testdata/31/env.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x03e8",
|
||||||
|
"currentGasLimit" : "0x1000000000",
|
||||||
|
"previousHash" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da",
|
||||||
|
"currentDataGasUsed" : "0x2000",
|
||||||
|
"parentTimestamp" : "0x00",
|
||||||
|
"parentDifficulty" : "0x00",
|
||||||
|
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"parentBeaconBlockRoot" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000",
|
||||||
|
"withdrawals" : [
|
||||||
|
],
|
||||||
|
"parentBaseFee" : "0x08",
|
||||||
|
"parentGasUsed" : "0x00",
|
||||||
|
"parentGasLimit" : "0x1000000000",
|
||||||
|
"parentExcessBlobGas" : "0x1000",
|
||||||
|
"parentBlobGasUsed" : "0x2000"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
"hello world"
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{"pc":0,"op":96,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
|
{"pc":2,"op":96,"gas":"0x13495","gasCost":"0x3","memSize":0,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
|
{"pc":4,"op":96,"gas":"0x13492","gasCost":"0x3","memSize":0,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
|
{"pc":6,"op":96,"gas":"0x1348f","gasCost":"0x3","memSize":0,"stack":["0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
|
{"pc":8,"op":0,"gas":"0x1348c","gasCost":"0x0","memSize":0,"stack":["0x40","0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"STOP"}
|
||||||
|
{"output":"","gasUsed":"0xc"}
|
||||||
14
cmd/evm/testdata/31/txs.json
vendored
Normal file
14
cmd/evm/testdata/31/txs.json
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"gas": "0x186a0",
|
||||||
|
"gasPrice": "0x600",
|
||||||
|
"input": "0x",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"to": "0x1111111111111111111111111111111111111111",
|
||||||
|
"value": "0x1",
|
||||||
|
"v" : "0x0",
|
||||||
|
"r" : "0x0",
|
||||||
|
"s" : "0x0",
|
||||||
|
"secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -3248,7 +3248,7 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout).Hooks(),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
|
|
@ -3330,7 +3330,7 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout).Hooks(),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ type ScopeContext struct {
|
||||||
Contract *Contract
|
Contract *Contract
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MemoryData returns the underlying memory slice. Callers must not modify the contents
|
||||||
|
// of the returned data.
|
||||||
func (ctx *ScopeContext) MemoryData() []byte {
|
func (ctx *ScopeContext) MemoryData() []byte {
|
||||||
if ctx.Memory == nil {
|
if ctx.Memory == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -50,6 +52,8 @@ func (ctx *ScopeContext) MemoryData() []byte {
|
||||||
return ctx.Memory.Data()
|
return ctx.Memory.Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MemoryData returns the stack data. Callers must not modify the contents
|
||||||
|
// of the returned data.
|
||||||
func (ctx *ScopeContext) StackData() []uint256.Int {
|
func (ctx *ScopeContext) StackData() []uint256.Int {
|
||||||
if ctx.Stack == nil {
|
if ctx.Stack == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -57,18 +61,23 @@ func (ctx *ScopeContext) StackData() []uint256.Int {
|
||||||
return ctx.Stack.Data()
|
return ctx.Stack.Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller returns the current caller.
|
||||||
func (ctx *ScopeContext) Caller() common.Address {
|
func (ctx *ScopeContext) Caller() common.Address {
|
||||||
return ctx.Contract.Caller()
|
return ctx.Contract.Caller()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Address returns the address where this scope of execution is taking place.
|
||||||
func (ctx *ScopeContext) Address() common.Address {
|
func (ctx *ScopeContext) Address() common.Address {
|
||||||
return ctx.Contract.Address()
|
return ctx.Contract.Address()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallValue returns the value supplied with this call.
|
||||||
func (ctx *ScopeContext) CallValue() *big.Int {
|
func (ctx *ScopeContext) CallValue() *big.Int {
|
||||||
return ctx.Contract.Value()
|
return ctx.Contract.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallInput returns the input/calldata with this call. Callers must not modify
|
||||||
|
// the contents of the returned data.
|
||||||
func (ctx *ScopeContext) CallInput() []byte {
|
func (ctx *ScopeContext) CallInput() []byte {
|
||||||
return ctx.Contract.Input
|
return ctx.Contract.Input
|
||||||
}
|
}
|
||||||
|
|
@ -189,16 +198,16 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||||
contract.Input = input
|
contract.Input = input
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
defer func() {
|
defer func() { // this deferred method handles exit-with-error
|
||||||
if err != nil {
|
if err == nil {
|
||||||
if !logged {
|
return
|
||||||
if in.evm.Config.Tracer.OnOpcode != nil {
|
}
|
||||||
|
if !logged && in.evm.Config.Tracer.OnOpcode != nil {
|
||||||
in.evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
in.evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
||||||
}
|
}
|
||||||
} else if in.evm.Config.Tracer.OnFault != nil {
|
if logged && in.evm.Config.Tracer.OnFault != nil {
|
||||||
in.evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, in.evm.depth, VMErrorFromErr(err))
|
in.evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, in.evm.depth, VMErrorFromErr(err))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
// The Interpreter main run loop (contextual). This loop runs until either an
|
// The Interpreter main run loop (contextual). This loop runs until either an
|
||||||
|
|
|
||||||
|
|
@ -783,7 +783,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// Swap out the noop logger to the standard tracer
|
// Swap out the noop logger to the standard tracer
|
||||||
writer = bufio.NewWriter(dump)
|
writer = bufio.NewWriter(dump)
|
||||||
vmConf = vm.Config{
|
vmConf = vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(&logConfig, writer).Hooks(),
|
Tracer: logger.NewJSONLogger(&logConfig, writer),
|
||||||
EnablePreimageRecording: true,
|
EnablePreimageRecording: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JSONLogger struct {
|
type jsonLogger struct {
|
||||||
encoder *json.Encoder
|
encoder *json.Encoder
|
||||||
cfg *Config
|
cfg *Config
|
||||||
env *tracing.VMContext
|
env *tracing.VMContext
|
||||||
|
|
@ -35,15 +35,11 @@ type JSONLogger struct {
|
||||||
|
|
||||||
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
|
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
|
||||||
// into the provided stream.
|
// into the provided stream.
|
||||||
func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
|
func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
|
||||||
l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg}
|
l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
|
||||||
if l.cfg == nil {
|
if l.cfg == nil {
|
||||||
l.cfg = &Config{}
|
l.cfg = &Config{}
|
||||||
}
|
}
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *JSONLogger) Hooks() *tracing.Hooks {
|
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnTxStart: l.OnTxStart,
|
OnTxStart: l.OnTxStart,
|
||||||
OnExit: l.OnExit,
|
OnExit: l.OnExit,
|
||||||
|
|
@ -52,12 +48,12 @@ func (l *JSONLogger) Hooks() *tracing.Hooks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) OnFault(pc uint64, op byte, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
|
func (l *jsonLogger) OnFault(pc uint64, op byte, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||||
// TODO: Add rData to this interface as well
|
// TODO: Add rData to this interface as well
|
||||||
l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
|
l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (l *jsonLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
memory := scope.MemoryData()
|
memory := scope.MemoryData()
|
||||||
stack := scope.StackData()
|
stack := scope.StackData()
|
||||||
|
|
||||||
|
|
@ -83,7 +79,7 @@ func (l *JSONLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracin
|
||||||
l.encoder.Encode(log)
|
l.encoder.Encode(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
func (l *jsonLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
if depth > 0 {
|
if depth > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +95,6 @@ func (l *JSONLogger) OnExit(depth int, output []byte, gasUsed uint64, err error,
|
||||||
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
|
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (l *jsonLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
l.env = env
|
l.env = env
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
w := bufio.NewWriter(buf)
|
w := bufio.NewWriter(buf)
|
||||||
config.Tracer = logger.NewJSONLogger(&logger.Config{}, w).Hooks()
|
config.Tracer = logger.NewJSONLogger(&logger.Config{}, w)
|
||||||
err2 := test(config)
|
err2 := test(config)
|
||||||
if !reflect.DeepEqual(err, err2) {
|
if !reflect.DeepEqual(err, err2) {
|
||||||
t.Errorf("different error for second run: %v", err2)
|
t.Errorf("different error for second run: %v", err2)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue