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  }