Skip to content

Commit 9b99f2e

Browse files
fix bug and optimize fill_trace logic for gc (ethereum#104)
* fix bug and upgrade trace code * minor * refactor (ethereum#105) * move * add comments * fix typo * update comments * rename extraData() * update comments Co-authored-by: HAOYUatHZ <[email protected]> Co-authored-by: HAOYUatHZ <[email protected]>
1 parent 9199413 commit 9b99f2e

File tree

3 files changed

+63
-88
lines changed

3 files changed

+63
-88
lines changed

core/types/l2trace.go

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
package types
22

33
import (
4+
"runtime"
5+
"sync"
6+
47
"github.com/scroll-tech/go-ethereum/common"
58
"github.com/scroll-tech/go-ethereum/common/hexutil"
69
)
710

11+
var (
12+
loggerResPool = sync.Pool{
13+
New: func() interface{} {
14+
// init arrays here; other types are inited with default values
15+
return &StructLogRes{
16+
Stack: []string{},
17+
Memory: []string{},
18+
}
19+
},
20+
}
21+
)
22+
823
// BlockResult contains block execution traces and results required for rollers.
924
type BlockResult struct {
1025
BlockTrace *BlockTrace `json:"blockTrace"`
@@ -25,8 +40,8 @@ type ExecutionResult struct {
2540
// It's exist only when tx is a contract call.
2641
CodeHash *common.Hash `json:"codeHash,omitempty"`
2742
// If it is a contract call, the contract code is returned.
28-
ByteCode string `json:"byteCode,omitempty"`
29-
StructLogs []StructLogRes `json:"structLogs"`
43+
ByteCode string `json:"byteCode,omitempty"`
44+
StructLogs []*StructLogRes `json:"structLogs"`
3045
}
3146

3247
// StructLogRes stores a structured log emitted by the EVM while replaying a
@@ -37,14 +52,30 @@ type StructLogRes struct {
3752
Gas uint64 `json:"gas"`
3853
GasCost uint64 `json:"gasCost"`
3954
Depth int `json:"depth"`
40-
Error string `json:"error,omitempty"`
55+
Error error `json:"error,omitempty"`
4156
Stack []string `json:"stack,omitempty"`
4257
Memory []string `json:"memory,omitempty"`
4358
Storage map[string]string `json:"storage,omitempty"`
4459
RefundCounter uint64 `json:"refund,omitempty"`
4560
ExtraData *ExtraData `json:"extraData,omitempty"`
4661
}
4762

63+
// Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization;
64+
// still need to fill in with Stack&Memory&Storage&ExtraData
65+
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) *StructLogRes {
66+
logRes := loggerResPool.Get().(*StructLogRes)
67+
logRes.Pc, logRes.Op, logRes.Gas, logRes.GasCost, logRes.Depth, logRes.RefundCounter = pc, op, gas, gasCost, depth, refundCounter
68+
logRes.Error = err
69+
runtime.SetFinalizer(logRes, func(logRes *StructLogRes) {
70+
logRes.Stack = logRes.Stack[:0]
71+
logRes.Memory = logRes.Memory[:0]
72+
logRes.Storage = nil
73+
logRes.ExtraData = nil
74+
loggerResPool.Put(logRes)
75+
})
76+
return logRes
77+
}
78+
4879
type ExtraData struct {
4980
// CALL | CALLCODE | DELEGATECALL | STATICCALL: [tx.to address’s code, stack.nth_last(1) address’s code]
5081
CodeList [][]byte `json:"codeList,omitempty"`
@@ -73,30 +104,3 @@ type StorageProofWrapper struct {
73104
Value string `json:"value,omitempty"`
74105
Proof []string `json:"proof,omitempty"`
75106
}
76-
77-
// NewExtraData create, init and return ExtraData
78-
func NewExtraData() *ExtraData {
79-
return &ExtraData{
80-
CodeList: make([][]byte, 0),
81-
ProofList: make([]*AccountProofWrapper, 0),
82-
}
83-
}
84-
85-
func (e *ExtraData) Clean() {
86-
e.CodeList = e.CodeList[:0]
87-
e.ProofList = e.ProofList[:0]
88-
}
89-
90-
// SealExtraData doesn't show empty fields.
91-
func (e *ExtraData) SealExtraData() *ExtraData {
92-
if len(e.CodeList) == 0 {
93-
e.CodeList = nil
94-
}
95-
if len(e.ProofList) == 0 {
96-
e.ProofList = nil
97-
}
98-
if e.CodeList == nil && e.ProofList == nil {
99-
return nil
100-
}
101-
return e
102-
}

core/vm/logger.go

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,14 @@ var (
8585
loggerPool = sync.Pool{
8686
New: func() interface{} {
8787
return &StructLog{
88-
Stack: make([]uint256.Int, 0),
89-
ExtraData: types.NewExtraData(),
88+
// init arrays here; other types are inited with default values
89+
Stack: make([]uint256.Int, 0),
9090
}
9191
},
9292
}
9393
)
9494

9595
func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int) *StructLog {
96-
9796
structlog := loggerPool.Get().(*StructLog)
9897
structlog.Pc, structlog.Op, structlog.Gas, structlog.GasCost, structlog.Depth = pc, op, gas, cost, depth
9998

@@ -109,7 +108,14 @@ func (s *StructLog) clean() {
109108
s.Stack = s.Stack[:0]
110109
s.ReturnData.Reset()
111110
s.Storage = nil
112-
s.ExtraData.Clean()
111+
s.ExtraData = nil
112+
}
113+
114+
func (s *StructLog) getOrInitExtraData() *types.ExtraData {
115+
if s.ExtraData == nil {
116+
s.ExtraData = &types.ExtraData{}
117+
}
118+
return s.ExtraData
113119
}
114120

115121
// overrides for gencodec
@@ -236,7 +242,7 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
236242
l.storage[contractAddress][storageKey] = storageValue
237243
structlog.Storage = l.storage[contractAddress].Copy()
238244

239-
if err := traceStorageProof(l, scope, structlog.ExtraData); err != nil {
245+
if err := traceStorageProof(l, scope, structlog.getOrInitExtraData()); err != nil {
240246
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
241247
}
242248
}
@@ -247,7 +253,7 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
247253
if ok {
248254
// execute trace func list.
249255
for _, exec := range execFuncList {
250-
if err = exec(l, scope, structlog.ExtraData); err != nil {
256+
if err = exec(l, scope, structlog.getOrInitExtraData()); err != nil {
251257
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
252258
}
253259
}
@@ -441,63 +447,28 @@ func (t *mdLogger) CaptureEnter(typ OpCode, from common.Address, to common.Addre
441447

442448
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
443449

444-
var (
445-
formatPool = sync.Pool{
446-
New: func() interface{} {
447-
return make([]types.StructLogRes, 0, 128)
448-
},
449-
}
450-
)
451-
452450
// FormatLogs formats EVM returned structured logs for json output
453-
func FormatLogs(logs []StructLog) []types.StructLogRes {
454-
formatted := formatPool.Get().([]types.StructLogRes)
455-
runtime.SetFinalizer(&formatted, func(format *[]types.StructLogRes) {
456-
for _, res := range *format {
457-
res.ExtraData = nil
458-
res.Storage = nil
459-
res.Stack = res.Stack[:0]
460-
res.Memory = res.Memory[:0]
461-
}
462-
formatPool.Put(*format)
463-
})
451+
func FormatLogs(logs []StructLog) []*types.StructLogRes {
452+
formatted := make([]*types.StructLogRes, 0, len(logs))
464453

465-
for index, trace := range logs {
466-
formatted = append(formatted, types.StructLogRes{
467-
Pc: trace.Pc,
468-
Op: trace.Op.String(),
469-
Gas: trace.Gas,
470-
GasCost: trace.GasCost,
471-
Depth: trace.Depth,
472-
RefundCounter: trace.RefundCounter,
473-
Error: trace.ErrorString(),
474-
})
475-
if len(trace.Stack) != 0 {
476-
if formatted[index].Stack == nil {
477-
formatted[index].Stack = make([]string, 0, len(trace.Stack))
478-
}
479-
for _, stackValue := range trace.Stack {
480-
formatted[index].Stack = append(formatted[index].Stack, stackValue.Hex())
481-
}
454+
for _, trace := range logs {
455+
logRes := types.NewStructLogResBasic(trace.Pc, trace.Op.String(), trace.Gas, trace.GasCost, trace.Depth, trace.RefundCounter, trace.Err)
456+
for _, stackValue := range trace.Stack {
457+
logRes.Stack = append(logRes.Stack, stackValue.Hex())
482458
}
483-
if trace.Memory.Len() != 0 {
484-
if formatted[index].Memory == nil {
485-
formatted[index].Memory = make([]string, 0, (trace.Memory.Len()+31)/32)
486-
}
487-
for i := 0; i+32 <= trace.Memory.Len(); i += 32 {
488-
formatted[index].Memory = append(formatted[index].Memory, common.Bytes2Hex(trace.Memory.Bytes()[i:i+32]))
489-
}
459+
for i := 0; i+32 <= trace.Memory.Len(); i += 32 {
460+
logRes.Memory = append(logRes.Memory, common.Bytes2Hex(trace.Memory.Bytes()[i:i+32]))
490461
}
491462
if len(trace.Storage) != 0 {
492463
storage := make(map[string]string)
493464
for i, storageValue := range trace.Storage {
494465
storage[i.Hex()] = storageValue.Hex()
495466
}
496-
formatted[index].Storage = storage
497-
}
498-
if trace.ExtraData != nil {
499-
formatted[index].ExtraData = trace.ExtraData.SealExtraData()
467+
logRes.Storage = storage
500468
}
469+
logRes.ExtraData = trace.ExtraData
470+
471+
formatted = append(formatted, logRes)
501472
}
502473
return formatted
503474
}

eth/tracers/api_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func TestTraceCall(t *testing.T) {
217217
Gas: params.TxGas,
218218
Failed: false,
219219
ReturnValue: "",
220-
StructLogs: []types.StructLogRes{},
220+
StructLogs: []*types.StructLogRes{},
221221
},
222222
},
223223
// Standard JSON trace upon the head, plain transfer.
@@ -234,7 +234,7 @@ func TestTraceCall(t *testing.T) {
234234
Gas: params.TxGas,
235235
Failed: false,
236236
ReturnValue: "",
237-
StructLogs: []types.StructLogRes{},
237+
StructLogs: []*types.StructLogRes{},
238238
},
239239
},
240240
// Standard JSON trace upon the non-existent block, error expects
@@ -263,7 +263,7 @@ func TestTraceCall(t *testing.T) {
263263
Gas: params.TxGas,
264264
Failed: false,
265265
ReturnValue: "",
266-
StructLogs: []types.StructLogRes{},
266+
StructLogs: []*types.StructLogRes{},
267267
},
268268
},
269269
// Standard JSON trace upon the pending block
@@ -280,7 +280,7 @@ func TestTraceCall(t *testing.T) {
280280
Gas: params.TxGas,
281281
Failed: false,
282282
ReturnValue: "",
283-
StructLogs: []types.StructLogRes{},
283+
StructLogs: []*types.StructLogRes{},
284284
},
285285
},
286286
}
@@ -333,7 +333,7 @@ func TestTraceTransaction(t *testing.T) {
333333
Gas: params.TxGas,
334334
Failed: false,
335335
ReturnValue: "",
336-
StructLogs: []types.StructLogRes{},
336+
StructLogs: []*types.StructLogRes{},
337337
}) {
338338
t.Error("Transaction tracing result is different")
339339
}

0 commit comments

Comments
 (0)