github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/tracer.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "math/big" 6 "time" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/core" 10 "github.com/ethereum/go-ethereum/core/vm" 11 "github.com/ethereum/go-ethereum/eth/tracers" 12 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 13 json "github.com/json-iterator/go" 14 ) 15 16 type TraceConfig struct { 17 // custom javascript tracer 18 Tracer string `json:"tracer"` 19 // disable stack capture 20 DisableStack bool `json:"disableStack"` 21 // disable storage capture 22 DisableStorage bool `json:"disableStorage"` 23 // print output during capture end 24 Debug bool `json:"debug"` 25 // enable memory capture 26 DisableMemory bool `json:"disableMemory"` 27 // enable return data capture 28 DisableReturnData bool `json:"disableReturnData"` 29 } 30 31 func GetTracerResult(tracer vm.Tracer, result *core.ExecutionResult) ([]byte, error) { 32 var ( 33 res []byte 34 err error 35 ) 36 // Depending on the tracer type, format and return the output 37 switch tracer := tracer.(type) { 38 case *vm.StructLogger: 39 // If the result contains a revert reason, return it. 40 returnVal := fmt.Sprintf("%x", result.Return()) 41 if len(result.Revert()) > 0 { 42 returnVal = fmt.Sprintf("%x", result.Revert()) 43 } 44 res, err = json.ConfigFastest.Marshal(&TraceExecutionResult{ 45 Gas: result.UsedGas, 46 Failed: result.Failed(), 47 ReturnValue: returnVal, 48 StructLogs: FormatLogs(tracer.StructLogs()), 49 }) 50 case *tracers.Tracer: 51 res, err = tracer.GetResult() 52 default: 53 res = []byte(fmt.Sprintf("bad tracer type %T", tracer)) 54 } 55 return res, err 56 } 57 58 // NoOpTracer is an empty implementation of vm.Tracer interface 59 type NoOpTracer struct{} 60 61 // NewNoOpTracer creates a no-op vm.Tracer 62 func NewNoOpTracer() *NoOpTracer { 63 return &NoOpTracer{} 64 } 65 66 // CaptureStart implements vm.Tracer interface 67 func (dt NoOpTracer) CaptureStart( 68 env *vm.EVM, 69 from, to common.Address, 70 create bool, 71 input []byte, 72 gas uint64, 73 value *big.Int, 74 ) { 75 } 76 77 // CaptureEnter implements vm.Tracer interface 78 func (dt NoOpTracer) CaptureEnter( 79 typ vm.OpCode, 80 from common.Address, 81 to common.Address, 82 input []byte, 83 gas uint64, 84 value *big.Int, 85 ) { 86 } 87 88 // CaptureExit implements vm.Tracer interface 89 func (dt NoOpTracer) CaptureExit(output []byte, gasUsed uint64, err error) {} 90 91 // CaptureState implements vm.Tracer interface 92 func (dt NoOpTracer) CaptureState( 93 env *vm.EVM, 94 pc uint64, 95 op vm.OpCode, 96 gas, cost uint64, 97 scope *vm.ScopeContext, 98 rData []byte, 99 depth int, 100 err error, 101 ) { 102 } 103 104 // CaptureFault implements vm.Tracer interface 105 func (dt NoOpTracer) CaptureFault( 106 env *vm.EVM, 107 pc uint64, 108 op vm.OpCode, 109 gas, cost uint64, 110 scope *vm.ScopeContext, 111 depth int, 112 err error, 113 ) { 114 } 115 116 // CaptureEnd implements vm.Tracer interface 117 func (dt NoOpTracer) CaptureEnd( 118 output []byte, 119 gasUsed uint64, 120 t time.Duration, 121 err error, 122 ) { 123 } 124 func defaultTracerConfig() *TraceConfig { 125 return &TraceConfig{ 126 Tracer: "", 127 DisableMemory: false, 128 DisableStorage: false, 129 DisableStack: false, 130 DisableReturnData: false, 131 Debug: false, 132 } 133 } 134 func TestTracerConfig(traceConfig *TraceConfig) error { 135 if traceConfig.Tracer != "" { 136 _, err := tracers.New(traceConfig.Tracer, &tracers.Context{}) 137 if err != nil { 138 return err 139 } 140 } 141 return nil 142 } 143 func newTracer(ctx sdk.Context, txHash *common.Hash) (tracer vm.Tracer) { 144 if ctx.IsTraceTxLog() { 145 var err error 146 configBytes := ctx.TraceTxLogConfig() 147 traceConfig := &TraceConfig{} 148 if configBytes == nil { 149 traceConfig = defaultTracerConfig() 150 } else { 151 err = json.Unmarshal(configBytes, traceConfig) 152 if err != nil { 153 return NewNoOpTracer() 154 } 155 } 156 if traceConfig.Tracer == "" { 157 //Basic tracer with config 158 logConfig := vm.LogConfig{ 159 DisableMemory: traceConfig.DisableMemory, 160 DisableStorage: traceConfig.DisableStorage, 161 DisableStack: traceConfig.DisableStack, 162 DisableReturnData: traceConfig.DisableReturnData, 163 Debug: traceConfig.Debug, 164 } 165 return vm.NewStructLogger(&logConfig) 166 } 167 // Json-based tracer 168 tCtx := &tracers.Context{ 169 TxHash: *txHash, 170 } 171 tracer, err = tracers.New(traceConfig.Tracer, tCtx) 172 if err != nil { 173 return NewNoOpTracer() 174 } 175 return tracer 176 } else { 177 //no op tracer 178 return NewNoOpTracer() 179 } 180 }