package types import ( "encoding/json" "fmt" "runtime" "strings" "time" ) type ExecutionTrace struct { Msg *Message MsgRct *MessageReceipt Error string Duration time.Duration GasCharges []*GasTrace Subcalls []ExecutionTrace } type GasTrace struct { Name string Location []Loc TotalGas int64 ComputeGas int64 StorageGas int64 TotalVirtualGas int64 VirtualComputeGas int64 VirtualStorageGas int64 TimeTaken time.Duration Extra interface{} `json:",omitempty"` Callers []uintptr `json:"-"` } type Loc struct { File string Line int Function string } func (l Loc) Show() bool { ignorePrefix := []string{ "reflect.", "github.com/filecoin-project/lotus/chain/vm.(*Invoker).transform", "github.com/filecoin-project/go-amt-ipld/", } for _, pre := range ignorePrefix { if strings.HasPrefix(l.Function, pre) { return false } } return true } func (l Loc) String() string { file := strings.Split(l.File, "/") fn := strings.Split(l.Function, "/") var fnpkg string if len(fn) > 2 { fnpkg = strings.Join(fn[len(fn)-2:], "/") } else { fnpkg = l.Function } return fmt.Sprintf("%s@%s:%d", fnpkg, file[len(file)-1], l.Line) } func (l Loc) Important() bool { if strings.HasPrefix(l.Function, "github.com/filecoin-project/specs-actors/actors/builtin") { return true } return false } func (gt *GasTrace) MarshalJSON() ([]byte, error) { type GasTraceCopy GasTrace if len(gt.Location) == 0 { if len(gt.Callers) != 0 { frames := runtime.CallersFrames(gt.Callers) for { frame, more := frames.Next() if frame.Function == "github.com/filecoin-project/lotus/chain/vm.(*VM).ApplyMessage" { break } l := Loc{ File: frame.File, Line: frame.Line, Function: frame.Function, } gt.Location = append(gt.Location, l) if !more { break } } } } cpy := (*GasTraceCopy)(gt) return json.Marshal(cpy) }