From 676df18aec66450c798052149529fc6c3c0fcf9e Mon Sep 17 00:00:00 2001 From: georgehao Date: Tue, 18 Apr 2023 16:31:47 +0800 Subject: [PATCH 1/4] feat: fix oom bug --- core/types/l2trace.go | 40 ++++++++----------------- core/vm/gen_structlog.go | 2 +- core/vm/logger.go | 65 +++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 63 deletions(-) diff --git a/core/types/l2trace.go b/core/types/l2trace.go index a805dc187c9c..5ea219438c88 100644 --- a/core/types/l2trace.go +++ b/core/types/l2trace.go @@ -2,25 +2,10 @@ package types import ( "encoding/json" - "math/big" - "runtime" - "sync" - "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/params" -) - -var ( - loggerResPool = sync.Pool{ - New: func() interface{} { - // init arrays here; other types are inited with default values - return &StructLogRes{ - Stack: []string{}, - Memory: []string{}, - } - }, - } + "math/big" ) // BlockTrace contains block execution traces and results required for rollers. @@ -97,22 +82,21 @@ type StructLogRes struct { ExtraData *ExtraData `json:"extraData,omitempty"` } -// Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization; +// NewStructLogResBasic Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization; // still need to fill in with Stack&Memory&Storage&ExtraData func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) *StructLogRes { - logRes := loggerResPool.Get().(*StructLogRes) - logRes.Pc, logRes.Op, logRes.Gas, logRes.GasCost, logRes.Depth, logRes.RefundCounter = pc, op, gas, gasCost, depth, refundCounter + logRes := &StructLogRes{ + Pc: pc, + Op: op, + Gas: gas, + GasCost: gasCost, + Depth: depth, + RefundCounter: refundCounter, + } + if err != nil { logRes.Error = err.Error() } - runtime.SetFinalizer(logRes, func(logRes *StructLogRes) { - logRes.Stack = logRes.Stack[:0] - logRes.Memory = logRes.Memory[:0] - logRes.Storage = nil - logRes.ExtraData = nil - logRes.Error = "" - loggerResPool.Put(logRes) - }) return logRes } @@ -151,7 +135,7 @@ type AccountWrapper struct { Storage *StorageWrapper `json:"storage,omitempty"` // StorageWrapper can be empty if irrelated to storage operation } -// while key & value can also be retrieved from StructLogRes.Storage, +// StorageWrapper while key & value can also be retrieved from StructLogRes.Storage, // we still stored in here for roller's processing convenience. type StorageWrapper struct { Key string `json:"key,omitempty"` diff --git a/core/vm/gen_structlog.go b/core/vm/gen_structlog.go index 16d08ae48860..05e24512ca0d 100644 --- a/core/vm/gen_structlog.go +++ b/core/vm/gen_structlog.go @@ -15,7 +15,7 @@ import ( var _ = (*structLogMarshaling)(nil) // MarshalJSON marshals as JSON. -func (s StructLog) MarshalJSON() ([]byte, error) { +func (s *StructLog) MarshalJSON() ([]byte, error) { type StructLog struct { Pc uint64 `json:"pc"` Op OpCode `json:"op"` diff --git a/core/vm/logger.go b/core/vm/logger.go index 5ad22540669e..8ce3c45c9ac5 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -22,7 +22,6 @@ import ( "fmt" "io" "math/big" - "runtime" "strings" "sync" "time" @@ -81,26 +80,15 @@ type StructLog struct { Err error `json:"-"` } -var ( - loggerPool = sync.Pool{ - New: func() interface{} { - return &StructLog{ - // init arrays here; other types are inited with default values - Stack: make([]uint256.Int, 0), - } - }, - } -) - func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) *StructLog { - structlog := loggerPool.Get().(*StructLog) - structlog.Pc, structlog.Op, structlog.Gas, structlog.GasCost, structlog.Depth, structlog.Err = pc, op, gas, cost, depth, err - - runtime.SetFinalizer(structlog, func(logger *StructLog) { - logger.clean() - loggerPool.Put(logger) - }) - return structlog + return &StructLog{ + Pc: pc, + Op: op, + Gas: gas, + GasCost: cost, + Depth: depth, + Err: err, + } } func (s *StructLog) clean() { @@ -163,8 +151,9 @@ type EVMLogger interface { // a track record of modified storage which is used in reporting snapshots of the // contract their storage. type StructLogger struct { - cfg LogConfig - env *EVM + cfg LogConfig + env *EVM + structLogPool sync.Pool statesAffected map[common.Address]struct{} storage map[common.Address]Storage @@ -185,6 +174,14 @@ func NewStructLogger(cfg *LogConfig) *StructLogger { if cfg != nil { logger.cfg = *cfg } + + logger.structLogPool.New = func() any { + return &StructLog{ + // init arrays here; other types are inited with default values + Stack: make([]uint256.Int, 0), + } + } + return logger } @@ -225,7 +222,7 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop stack := scope.Stack contract := scope.Contract // create a struct log. - structlog := NewStructlog(pc, op, gas, cost, depth, opErr) + structLog := NewStructlog(pc, op, gas, cost, depth, opErr) // check if already accumulated the specified number of logs if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { @@ -233,12 +230,12 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop } // Copy a snapshot of the current memory state to a new buffer if l.cfg.EnableMemory { - structlog.Memory.Write(memory.Data()) - structlog.MemorySize = memory.Len() + structLog.Memory.Write(memory.Data()) + structLog.MemorySize = memory.Len() } // Copy a snapshot of the current stack state to a new buffer if !l.cfg.DisableStack { - structlog.Stack = append(structlog.Stack, stack.Data()...) + structLog.Stack = append(structLog.Stack, stack.Data()...) } var ( recordStorageDetail bool @@ -262,20 +259,20 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop l.storage[contractAddress] = make(Storage) } l.storage[contractAddress][storageKey] = storageValue - structlog.Storage = l.storage[contractAddress].Copy() + structLog.Storage = l.storage[contractAddress].Copy() - if err := traceStorage(l, scope, structlog.getOrInitExtraData()); err != nil { + if err := traceStorage(l, scope, structLog.getOrInitExtraData()); err != nil { log.Error("Failed to trace data", "opcode", op.String(), "err", err) } } if l.cfg.EnableReturnData { - structlog.ReturnData.Write(rData) + structLog.ReturnData.Write(rData) } execFuncList, ok := OpcodeExecs[op] if ok { // execute trace func list. for _, exec := range execFuncList { - if err := exec(l, scope, structlog.getOrInitExtraData()); err != nil { + if err := exec(l, scope, structLog.getOrInitExtraData()); err != nil { log.Error("Failed to trace data", "opcode", op.String(), "err", err) } } @@ -283,12 +280,12 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop // for each "calling" op, pick the caller's state switch op { case CALL, CALLCODE, STATICCALL, DELEGATECALL, CREATE, CREATE2: - extraData := structlog.getOrInitExtraData() + extraData := structLog.getOrInitExtraData() extraData.Caller = append(extraData.Caller, getWrappedAccountForAddr(l, scope.Contract.Address())) } - structlog.RefundCounter = l.env.StateDB.GetRefund() - l.logs = append(l.logs, structlog) + structLog.RefundCounter = l.env.StateDB.GetRefund() + l.logs = append(l.logs, structLog) } func (l *StructLogger) CaptureStateAfter(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) { @@ -335,7 +332,7 @@ func (l *StructLogger) CaptureEnter(typ OpCode, from common.Address, to common.A } } -// in CaptureExit phase, a CREATE has its target address's code being set and queryable +// CaptureExit phase, a CREATE has its target address's code being set and queryable func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) { stackH := len(l.callStackLogInd) if stackH == 0 { From b15dc80b9874278642e5dd2952d52fc72ba930cd Mon Sep 17 00:00:00 2001 From: georgehao Date: Tue, 18 Apr 2023 16:34:36 +0800 Subject: [PATCH 2/4] feat: format import --- core/types/l2trace.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/types/l2trace.go b/core/types/l2trace.go index 5ea219438c88..ef8fcdf5553e 100644 --- a/core/types/l2trace.go +++ b/core/types/l2trace.go @@ -2,10 +2,11 @@ package types import ( "encoding/json" + "math/big" + "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/params" - "math/big" ) // BlockTrace contains block execution traces and results required for rollers. From 3a74778b8bd596c334bb3fb237cc53f0790afd79 Mon Sep 17 00:00:00 2001 From: georgehao Date: Tue, 18 Apr 2023 17:01:18 +0800 Subject: [PATCH 3/4] feat: remove unused code --- core/vm/logger.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/core/vm/logger.go b/core/vm/logger.go index 8ce3c45c9ac5..c5dcd5c36834 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -23,7 +23,6 @@ import ( "io" "math/big" "strings" - "sync" "time" "github.com/holiman/uint256" @@ -151,9 +150,8 @@ type EVMLogger interface { // a track record of modified storage which is used in reporting snapshots of the // contract their storage. type StructLogger struct { - cfg LogConfig - env *EVM - structLogPool sync.Pool + cfg LogConfig + env *EVM statesAffected map[common.Address]struct{} storage map[common.Address]Storage @@ -175,13 +173,6 @@ func NewStructLogger(cfg *LogConfig) *StructLogger { logger.cfg = *cfg } - logger.structLogPool.New = func() any { - return &StructLog{ - // init arrays here; other types are inited with default values - Stack: make([]uint256.Int, 0), - } - } - return logger } From c1301618c10adee84bae036bf5270f1ec856e8ba Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Wed, 19 Apr 2023 21:09:38 +0800 Subject: [PATCH 4/4] Update version.go --- params/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/version.go b/params/version.go index 436d4c26f9dc..a681346c6d03 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 3 // Major version component of the current release VersionMinor = 1 // Minor version component of the current release - VersionPatch = 5 // Patch version component of the current release + VersionPatch = 6 // Patch version component of the current release VersionMeta = "alpha" // Version metadata to append to the version string )