Skip to content

Commit 0cecc19

Browse files
lispcomerfirmak
andauthored
refactor(trace): clean outdated fields (#842)
* clean trace: remove ExtraData, disable prestateTracer, collect bytecodes in top level * fix * fix * fix * fix * fix * more cleanup * more cleanup * refactor(trace): clean outdated fields * fix bytecodes in trace * chore: auto version bump [bot] * chore: auto version bump [bot] * use hexutil.Bytes --------- Co-authored-by: Ömer Faruk Irmak <omerfirmak@gmail.com> Co-authored-by: omerfirmak <omerfirmak@users.noreply.github.com> Co-authored-by: lispc <lispc@users.noreply.github.com>
1 parent df08f60 commit 0cecc19

File tree

5 files changed

+83
-159
lines changed

5 files changed

+83
-159
lines changed

core/types/l2trace.go

+9-31
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,21 @@ type BlockTrace struct {
1717
Header *Header `json:"header"`
1818
Transactions []*TransactionData `json:"transactions"`
1919
StorageTrace *StorageTrace `json:"storageTrace"`
20+
Bytecodes []*BytecodeTrace `json:"codes"`
2021
TxStorageTraces []*StorageTrace `json:"txStorageTraces,omitempty"`
2122
ExecutionResults []*ExecutionResult `json:"executionResults"`
2223
WithdrawTrieRoot common.Hash `json:"withdraw_trie_root,omitempty"`
2324
StartL1QueueIndex uint64 `json:"startL1QueueIndex"`
2425
}
2526

27+
// BytecodeTrace stores all accessed bytecodes
28+
type BytecodeTrace struct {
29+
CodeSize uint64 `json:"codeSize"`
30+
KeccakCodeHash common.Hash `json:"keccakCodeHash"`
31+
PoseidonCodeHash common.Hash `json:"hash"`
32+
Code hexutil.Bytes `json:"code"`
33+
}
34+
2635
// StorageTrace stores proofs of storage needed by storage circuit
2736
type StorageTrace struct {
2837
// Root hash before block execution:
@@ -61,13 +70,8 @@ type ExecutionResult struct {
6170
// currently they are just `from` and `to` account
6271
AccountsAfter []*AccountWrapper `json:"accountAfter"`
6372

64-
// `PoseidonCodeHash` only exists when tx is a contract call.
65-
PoseidonCodeHash *common.Hash `json:"poseidonCodeHash,omitempty"`
66-
// If it is a contract call, the contract code is returned.
67-
ByteCode string `json:"byteCode,omitempty"`
6873
StructLogs []*StructLogRes `json:"structLogs"`
6974
CallTrace json.RawMessage `json:"callTrace"`
70-
Prestate json.RawMessage `json:"prestate"`
7175
}
7276

7377
// StructLogRes stores a structured log emitted by the EVM while replaying a
@@ -83,7 +87,6 @@ type StructLogRes struct {
8387
Memory []string `json:"memory,omitempty"`
8488
Storage map[string]string `json:"storage,omitempty"`
8589
RefundCounter uint64 `json:"refund,omitempty"`
86-
ExtraData *ExtraData `json:"extraData,omitempty"`
8790
}
8891

8992
// NewStructLogResBasic Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization;
@@ -104,31 +107,6 @@ func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int,
104107
return logRes
105108
}
106109

107-
type ExtraData struct {
108-
// Indicate the call succeeds or not for CALL/CREATE op
109-
CallFailed bool `json:"callFailed,omitempty"`
110-
// CALL | CALLCODE | DELEGATECALL | STATICCALL: [tx.to address’s code, stack.nth_last(1) address’s code]
111-
// CREATE | CREATE2: [created contract’s code]
112-
// CODESIZE | CODECOPY: [contract’s code]
113-
// EXTCODESIZE | EXTCODECOPY: [stack.nth_last(0) address’s code]
114-
CodeList []string `json:"codeList,omitempty"`
115-
// SSTORE | SLOAD: [storageProof]
116-
// SELFDESTRUCT: [contract address’s account, stack.nth_last(0) address’s account]
117-
// SELFBALANCE: [contract address’s account]
118-
// BALANCE | EXTCODEHASH: [stack.nth_last(0) address’s account]
119-
// CREATE | CREATE2: [created contract address’s account (before constructed),
120-
// created contract address's account (after constructed)]
121-
// CALL | CALLCODE: [caller contract address’s account,
122-
// stack.nth_last(1) (i.e. callee) address’s account,
123-
// callee contract address's account (value updated, before called)]
124-
// STATICCALL: [stack.nth_last(1) (i.e. callee) address’s account,
125-
// callee contract address's account (before called)]
126-
StateList []*AccountWrapper `json:"proofList,omitempty"`
127-
// The status of caller, it would be captured twice:
128-
// 1. before execution and 2. updated in CaptureEnter (for CALL/CALLCODE it duplicated with StateList[0])
129-
Caller []*AccountWrapper `json:"caller,omitempty"`
130-
}
131-
132110
type AccountWrapper struct {
133111
Address common.Address `json:"address"`
134112
Nonce uint64 `json:"nonce"`

core/vm/logger.go

+20-55
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ type StructLog struct {
7676
Storage map[common.Hash]common.Hash `json:"-"`
7777
Depth int `json:"depth"`
7878
RefundCounter uint64 `json:"refund"`
79-
ExtraData *types.ExtraData `json:"extraData"`
8079
Err error `json:"-"`
8180
}
8281

@@ -96,17 +95,9 @@ func (s *StructLog) clean() {
9695
s.Stack = s.Stack[:0]
9796
s.ReturnData.Reset()
9897
s.Storage = nil
99-
s.ExtraData = nil
10098
s.Err = nil
10199
}
102100

103-
func (s *StructLog) getOrInitExtraData() *types.ExtraData {
104-
if s.ExtraData == nil {
105-
s.ExtraData = &types.ExtraData{}
106-
}
107-
return s.ExtraData
108-
}
109-
110101
// overrides for gencodec
111102
type structLogMarshaling struct {
112103
Gas math.HexOrDecimal64
@@ -145,6 +136,13 @@ type EVMLogger interface {
145136
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
146137
}
147138

139+
type CodeInfo struct {
140+
CodeSize uint64
141+
KeccakCodeHash common.Hash
142+
PoseidonCodeHash common.Hash
143+
Code []byte
144+
}
145+
148146
// StructLogger is an EVM state logger and implements EVMLogger.
149147
//
150148
// StructLogger can capture state based on the given Log configuration and also keeps
@@ -154,6 +152,8 @@ type StructLogger struct {
154152
cfg LogConfig
155153
env *EVM
156154

155+
bytecodes map[common.Hash]CodeInfo
156+
157157
statesAffected map[common.Address]struct{}
158158
storage map[common.Address]Storage
159159
createdAccount *types.AccountWrapper
@@ -167,6 +167,7 @@ type StructLogger struct {
167167
// NewStructLogger returns a new logger
168168
func NewStructLogger(cfg *LogConfig) *StructLogger {
169169
logger := &StructLogger{
170+
bytecodes: make(map[common.Hash]CodeInfo),
170171
storage: make(map[common.Address]Storage),
171172
statesAffected: make(map[common.Address]struct{}),
172173
}
@@ -179,6 +180,7 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
179180

180181
// Reset clears the data held by the logger.
181182
func (l *StructLogger) Reset() {
183+
l.bytecodes = make(map[common.Hash]CodeInfo)
182184
l.storage = make(map[common.Address]Storage)
183185
l.statesAffected = make(map[common.Address]struct{})
184186
l.output = make([]byte, 0)
@@ -200,6 +202,8 @@ func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Add
200202
Nonce: env.StateDB.GetNonce(to),
201203
Balance: (*hexutil.Big)(value),
202204
}
205+
} else {
206+
traceCodeWithAddress(l, to)
203207
}
204208

205209
l.statesAffected[from] = struct{}{}
@@ -260,17 +264,11 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
260264
if ok {
261265
// execute trace func list.
262266
for _, exec := range execFuncList {
263-
if err := exec(l, scope, structLog.getOrInitExtraData()); err != nil {
267+
if err := exec(l, scope); err != nil {
264268
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
265269
}
266270
}
267271
}
268-
// for each "calling" op, pick the caller's state
269-
switch op {
270-
case CALL, CALLCODE, STATICCALL, DELEGATECALL, CREATE, CREATE2:
271-
extraData := structLog.getOrInitExtraData()
272-
extraData.Caller = append(extraData.Caller, getWrappedAccountForAddr(l, scope.Contract.Address()))
273-
}
274272

275273
// in reality it is impossible for CREATE to trigger ErrContractAddressCollision
276274
if op == CREATE2 && opErr == nil {
@@ -288,9 +286,6 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
288286

289287
contractHash := l.env.StateDB.GetKeccakCodeHash(address)
290288
if l.env.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyKeccakCodeHash) {
291-
extraData := structLog.getOrInitExtraData()
292-
wrappedStatus := getWrappedAccountForAddr(l, address)
293-
extraData.StateList = append(extraData.StateList, wrappedStatus)
294289
l.statesAffected[address] = struct{}{}
295290
}
296291
}
@@ -331,16 +326,7 @@ func (l *StructLogger) CaptureEnter(typ OpCode, from common.Address, to common.A
331326
panic("unexpected evm depth in capture enter")
332327
}
333328
l.statesAffected[to] = struct{}{}
334-
theLog := l.logs[lastLogPos]
335-
theLog.getOrInitExtraData()
336-
// handling additional updating for CALL/STATICCALL/CALLCODE/CREATE/CREATE2 only
337-
// append extraData part for the log, capture the account status (the nonce / balance has been updated in capture enter)
338-
wrappedStatus := getWrappedAccountForAddr(l, to)
339-
theLog.ExtraData.StateList = append(theLog.ExtraData.StateList, wrappedStatus)
340-
// finally we update the caller's status (it is possible that nonce and balance being updated)
341-
if len(theLog.ExtraData.Caller) == 1 {
342-
theLog.ExtraData.Caller = append(theLog.ExtraData.Caller, getWrappedAccountForAddr(l, from))
343-
}
329+
344330
}
345331

346332
// CaptureExit phase, a CREATE has its target address's code being set and queryable
@@ -350,32 +336,7 @@ func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {
350336
panic("unexpected capture exit occur")
351337
}
352338

353-
theLogPos := l.callStackLogInd[stackH-1]
354339
l.callStackLogInd = l.callStackLogInd[:stackH-1]
355-
theLog := l.logs[theLogPos]
356-
// update "forecast" data
357-
if err != nil {
358-
theLog.ExtraData.CallFailed = true
359-
}
360-
361-
// handling updating for CREATE only
362-
switch theLog.Op {
363-
case CREATE, CREATE2:
364-
// append extraData part for the log whose op is CREATE(2), capture the account status (the codehash would be updated in capture exit)
365-
dataLen := len(theLog.ExtraData.StateList)
366-
if dataLen == 0 {
367-
panic("unexpected data capture for target op")
368-
}
369-
370-
lastAccData := theLog.ExtraData.StateList[dataLen-1]
371-
wrappedStatus := getWrappedAccountForAddr(l, lastAccData.Address)
372-
theLog.ExtraData.StateList = append(theLog.ExtraData.StateList, wrappedStatus)
373-
code := getCodeForAddr(l, lastAccData.Address)
374-
theLog.ExtraData.CodeList = append(theLog.ExtraData.CodeList, hexutil.Encode(code))
375-
default:
376-
//do nothing for other op code
377-
return
378-
}
379340

380341
}
381342

@@ -389,6 +350,11 @@ func (l *StructLogger) UpdatedStorages() map[common.Address]Storage {
389350
return l.storage
390351
}
391352

353+
// TracedBytecodes is used to collect all "touched" bytecodes
354+
func (l *StructLogger) TracedBytecodes() map[common.Hash]CodeInfo {
355+
return l.bytecodes
356+
}
357+
392358
// CreatedAccount return the account data in case it is a create tx
393359
func (l *StructLogger) CreatedAccount() *types.AccountWrapper { return l.createdAccount }
394360

@@ -540,7 +506,6 @@ func FormatLogs(logs []*StructLog) []*types.StructLogRes {
540506
}
541507
logRes.Storage = storage
542508
}
543-
logRes.ExtraData = trace.ExtraData
544509

545510
formatted = append(formatted, logRes)
546511
}

core/vm/logger_trace.go

+19-44
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package vm
22

33
import (
44
"github.com/scroll-tech/go-ethereum/common"
5-
"github.com/scroll-tech/go-ethereum/common/hexutil"
6-
"github.com/scroll-tech/go-ethereum/core/types"
75
)
86

9-
type traceFunc func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error
7+
type traceFunc func(l *StructLogger, scope *ScopeContext) error
108

119
var (
1210
// OpcodeExecs the map to load opcodes' trace funcs.
@@ -15,92 +13,69 @@ var (
1513
CALLCODE: {traceToAddressCode, traceLastNAddressCode(1), traceContractAccount, traceLastNAddressAccount(1)}, // contract account is the caller, stack.nth_last(1) is the callee's address
1614
DELEGATECALL: {traceToAddressCode, traceLastNAddressCode(1)},
1715
STATICCALL: {traceToAddressCode, traceLastNAddressCode(1), traceLastNAddressAccount(1)},
18-
CREATE: {}, // caller is already recorded in ExtraData.Caller, callee is recorded in CaptureEnter&CaptureExit
19-
CREATE2: {}, // caller is already recorded in ExtraData.Caller, callee is recorded in CaptureEnter&CaptureExit
20-
SLOAD: {}, // trace storage in `captureState` instead of here, to handle `l.cfg.DisableStorage` flag
21-
SSTORE: {}, // trace storage in `captureState` instead of here, to handle `l.cfg.DisableStorage` flag
2216
SELFDESTRUCT: {traceContractAccount, traceLastNAddressAccount(0)},
2317
SELFBALANCE: {traceContractAccount},
2418
BALANCE: {traceLastNAddressAccount(0)},
2519
EXTCODEHASH: {traceLastNAddressAccount(0)},
26-
CODESIZE: {traceContractCode},
27-
CODECOPY: {traceContractCode},
28-
EXTCODESIZE: {traceLastNAddressCode(0)},
20+
EXTCODESIZE: {traceLastNAddressAccount(0)},
2921
EXTCODECOPY: {traceLastNAddressCode(0)},
3022
}
3123
)
3224

3325
// traceToAddressCode gets tx.to address’s code
34-
func traceToAddressCode(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
26+
func traceToAddressCode(l *StructLogger, scope *ScopeContext) error {
3527
if l.env.To == nil {
3628
return nil
3729
}
38-
code := l.env.StateDB.GetCode(*l.env.To)
39-
extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
30+
traceCodeWithAddress(l, *l.env.To)
4031
return nil
4132
}
4233

4334
// traceLastNAddressCode
4435
func traceLastNAddressCode(n int) traceFunc {
45-
return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
36+
return func(l *StructLogger, scope *ScopeContext) error {
4637
stack := scope.Stack
4738
if stack.len() <= n {
4839
return nil
4940
}
5041
address := common.Address(stack.data[stack.len()-1-n].Bytes20())
51-
code := l.env.StateDB.GetCode(address)
52-
extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
42+
traceCodeWithAddress(l, address)
5343
l.statesAffected[address] = struct{}{}
5444
return nil
5545
}
5646
}
5747

58-
// traceContractCode gets the contract's code
59-
func traceContractCode(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
60-
code := l.env.StateDB.GetCode(scope.Contract.Address())
61-
extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
62-
return nil
48+
func traceCodeWithAddress(l *StructLogger, address common.Address) {
49+
code := l.env.StateDB.GetCode(address)
50+
keccakCodeHash := l.env.StateDB.GetKeccakCodeHash(address)
51+
poseidonCodeHash := l.env.StateDB.GetPoseidonCodeHash(address)
52+
codeSize := l.env.StateDB.GetCodeSize(address)
53+
l.bytecodes[poseidonCodeHash] = CodeInfo{
54+
codeSize,
55+
keccakCodeHash,
56+
poseidonCodeHash,
57+
code,
58+
}
6359
}
6460

6561
// traceContractAccount gets the contract's account
66-
func traceContractAccount(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
67-
// Get account state.
68-
state := getWrappedAccountForAddr(l, scope.Contract.Address())
69-
extraData.StateList = append(extraData.StateList, state)
62+
func traceContractAccount(l *StructLogger, scope *ScopeContext) error {
7063
l.statesAffected[scope.Contract.Address()] = struct{}{}
7164

7265
return nil
7366
}
7467

7568
// traceLastNAddressAccount returns func about the last N's address account.
7669
func traceLastNAddressAccount(n int) traceFunc {
77-
return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
70+
return func(l *StructLogger, scope *ScopeContext) error {
7871
stack := scope.Stack
7972
if stack.len() <= n {
8073
return nil
8174
}
8275

8376
address := common.Address(stack.data[stack.len()-1-n].Bytes20())
84-
state := getWrappedAccountForAddr(l, address)
85-
extraData.StateList = append(extraData.StateList, state)
8677
l.statesAffected[address] = struct{}{}
8778

8879
return nil
8980
}
9081
}
91-
92-
// StorageWrapper will be empty
93-
func getWrappedAccountForAddr(l *StructLogger, address common.Address) *types.AccountWrapper {
94-
return &types.AccountWrapper{
95-
Address: address,
96-
Nonce: l.env.StateDB.GetNonce(address),
97-
Balance: (*hexutil.Big)(l.env.StateDB.GetBalance(address)),
98-
KeccakCodeHash: l.env.StateDB.GetKeccakCodeHash(address),
99-
PoseidonCodeHash: l.env.StateDB.GetPoseidonCodeHash(address),
100-
CodeSize: l.env.StateDB.GetCodeSize(address),
101-
}
102-
}
103-
104-
func getCodeForAddr(l *StructLogger, address common.Address) []byte {
105-
return l.env.StateDB.GetCode(address)
106-
}

params/version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 5 // Minor version component of the current release
27-
VersionPatch = 11 // Patch version component of the current release
27+
VersionPatch = 12 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

0 commit comments

Comments
 (0)