diff --git a/core/types/l2trace.go b/core/types/l2trace.go index 135d4542ba..70639d7434 100644 --- a/core/types/l2trace.go +++ b/core/types/l2trace.go @@ -32,17 +32,17 @@ type ExecutionResult struct { // StructLogRes stores a structured log emitted by the EVM while replaying a // transaction in debug mode type StructLogRes struct { - Pc uint64 `json:"pc"` - Op string `json:"op"` - Gas uint64 `json:"gas"` - GasCost uint64 `json:"gasCost"` - Depth int `json:"depth"` - Error string `json:"error,omitempty"` - Stack *[]string `json:"stack,omitempty"` - Memory *[]string `json:"memory,omitempty"` - Storage *map[string]string `json:"storage,omitempty"` - RefundCounter uint64 `json:"refund,omitempty"` - ExtraData *ExtraData `json:"extraData,omitempty"` + Pc uint64 `json:"pc"` + Op string `json:"op"` + Gas uint64 `json:"gas"` + GasCost uint64 `json:"gasCost"` + Depth int `json:"depth"` + Error string `json:"error,omitempty"` + Stack []string `json:"stack,omitempty"` + Memory []string `json:"memory,omitempty"` + Storage map[string]string `json:"storage,omitempty"` + RefundCounter uint64 `json:"refund,omitempty"` + ExtraData *ExtraData `json:"extraData,omitempty"` } type ExtraData struct { diff --git a/core/vm/logger.go b/core/vm/logger.go index d5c88bf39a..8d801f3876 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -441,11 +441,29 @@ func (t *mdLogger) CaptureEnter(typ OpCode, from common.Address, to common.Addre func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} +var ( + formatPool = sync.Pool{ + New: func() interface{} { + return make([]types.StructLogRes, 0, 128) + }, + } +) + // FormatLogs formats EVM returned structured logs for json output func FormatLogs(logs []StructLog) []types.StructLogRes { - formatted := make([]types.StructLogRes, len(logs)) + formatted := formatPool.Get().([]types.StructLogRes) + runtime.SetFinalizer(&formatted, func(format *[]types.StructLogRes) { + for _, res := range *format { + res.ExtraData = nil + res.Storage = nil + res.Stack = res.Stack[:0] + res.Memory = res.Memory[:0] + } + formatPool.Put(*format) + }) + for index, trace := range logs { - formatted[index] = types.StructLogRes{ + formatted = append(formatted, types.StructLogRes{ Pc: trace.Pc, Op: trace.Op.String(), Gas: trace.Gas, @@ -453,27 +471,29 @@ func FormatLogs(logs []StructLog) []types.StructLogRes { Depth: trace.Depth, RefundCounter: trace.RefundCounter, Error: trace.ErrorString(), - } + }) if len(trace.Stack) != 0 { - stack := make([]string, len(trace.Stack)) - for i, stackValue := range trace.Stack { - stack[i] = stackValue.Hex() + if formatted[index].Stack == nil { + formatted[index].Stack = make([]string, 0, len(trace.Stack)) + } + for _, stackValue := range trace.Stack { + formatted[index].Stack = append(formatted[index].Stack, stackValue.Hex()) } - formatted[index].Stack = &stack } if trace.Memory.Len() != 0 { - memory := make([]string, 0, (trace.Memory.Len()+31)/32) - for i := 0; i+32 <= trace.Memory.Len(); i += 32 { - memory = append(memory, fmt.Sprintf("%x", trace.Memory.Bytes()[i:i+32])) + if formatted[index].Memory == nil { + formatted[index].Memory = make([]string, 0, (trace.Memory.Len()+31)/32) + } + for i := 0; i+32 <= trace.Memory.Len(); i += 32 { + formatted[index].Memory = append(formatted[index].Memory, common.Bytes2Hex(trace.Memory.Bytes()[i:i+32])) } - formatted[index].Memory = &memory } if len(trace.Storage) != 0 { storage := make(map[string]string) for i, storageValue := range trace.Storage { - storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue) + storage[i.Hex()] = storageValue.Hex() } - formatted[index].Storage = &storage + formatted[index].Storage = storage } if trace.ExtraData != nil { formatted[index].ExtraData = trace.ExtraData.SealExtraData() diff --git a/core/vm/logger_trace.go b/core/vm/logger_trace.go index db100599ae..5b0eccfd90 100644 --- a/core/vm/logger_trace.go +++ b/core/vm/logger_trace.go @@ -161,12 +161,13 @@ func getWrappedProofForStorage(l *StructLogger, address common.Address, key comm }, nil } -func encodeProof(proof [][]byte) (res []string) { +func encodeProof(proof [][]byte) []string { if len(proof) == 0 { return nil } + res := make([]string, 0, len(proof)) for _, node := range proof { res = append(res, hexutil.Encode(node)) } - return + return res }