mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
fix(api): fix debug_ API oom bug (#284)
* feat: fix oom bug * feat: format import * feat: remove unused code * Update version.go --------- Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
This commit is contained in:
parent
b22944a621
commit
f71fc6794a
4 changed files with 34 additions and 61 deletions
|
|
@ -3,26 +3,12 @@ package types
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/scroll-tech/go-ethereum/common"
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||||
"github.com/scroll-tech/go-ethereum/params"
|
"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{},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// BlockTrace contains block execution traces and results required for rollers.
|
// BlockTrace contains block execution traces and results required for rollers.
|
||||||
type BlockTrace struct {
|
type BlockTrace struct {
|
||||||
ChainID uint64 `json:"chainID"`
|
ChainID uint64 `json:"chainID"`
|
||||||
|
|
@ -97,22 +83,21 @@ type StructLogRes struct {
|
||||||
ExtraData *ExtraData `json:"extraData,omitempty"`
|
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
|
// 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 {
|
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) *StructLogRes {
|
||||||
logRes := loggerResPool.Get().(*StructLogRes)
|
logRes := &StructLogRes{
|
||||||
logRes.Pc, logRes.Op, logRes.Gas, logRes.GasCost, logRes.Depth, logRes.RefundCounter = pc, op, gas, gasCost, depth, refundCounter
|
Pc: pc,
|
||||||
|
Op: op,
|
||||||
|
Gas: gas,
|
||||||
|
GasCost: gasCost,
|
||||||
|
Depth: depth,
|
||||||
|
RefundCounter: refundCounter,
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logRes.Error = err.Error()
|
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
|
return logRes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +136,7 @@ type AccountWrapper struct {
|
||||||
Storage *StorageWrapper `json:"storage,omitempty"` // StorageWrapper can be empty if irrelated to storage operation
|
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.
|
// we still stored in here for roller's processing convenience.
|
||||||
type StorageWrapper struct {
|
type StorageWrapper struct {
|
||||||
Key string `json:"key,omitempty"`
|
Key string `json:"key,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import (
|
||||||
var _ = (*structLogMarshaling)(nil)
|
var _ = (*structLogMarshaling)(nil)
|
||||||
|
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (s StructLog) MarshalJSON() ([]byte, error) {
|
func (s *StructLog) MarshalJSON() ([]byte, error) {
|
||||||
type StructLog struct {
|
type StructLog struct {
|
||||||
Pc uint64 `json:"pc"`
|
Pc uint64 `json:"pc"`
|
||||||
Op OpCode `json:"op"`
|
Op OpCode `json:"op"`
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -81,26 +79,15 @@ type StructLog struct {
|
||||||
Err error `json:"-"`
|
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 {
|
func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) *StructLog {
|
||||||
structlog := loggerPool.Get().(*StructLog)
|
return &StructLog{
|
||||||
structlog.Pc, structlog.Op, structlog.Gas, structlog.GasCost, structlog.Depth, structlog.Err = pc, op, gas, cost, depth, err
|
Pc: pc,
|
||||||
|
Op: op,
|
||||||
runtime.SetFinalizer(structlog, func(logger *StructLog) {
|
Gas: gas,
|
||||||
logger.clean()
|
GasCost: cost,
|
||||||
loggerPool.Put(logger)
|
Depth: depth,
|
||||||
})
|
Err: err,
|
||||||
return structlog
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StructLog) clean() {
|
func (s *StructLog) clean() {
|
||||||
|
|
@ -185,6 +172,7 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
|
||||||
if cfg != nil {
|
if cfg != nil {
|
||||||
logger.cfg = *cfg
|
logger.cfg = *cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
return logger
|
return logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +213,7 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
contract := scope.Contract
|
contract := scope.Contract
|
||||||
// create a struct log.
|
// 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
|
// check if already accumulated the specified number of logs
|
||||||
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
|
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
|
||||||
|
|
@ -233,12 +221,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
|
// Copy a snapshot of the current memory state to a new buffer
|
||||||
if l.cfg.EnableMemory {
|
if l.cfg.EnableMemory {
|
||||||
structlog.Memory.Write(memory.Data())
|
structLog.Memory.Write(memory.Data())
|
||||||
structlog.MemorySize = memory.Len()
|
structLog.MemorySize = memory.Len()
|
||||||
}
|
}
|
||||||
// Copy a snapshot of the current stack state to a new buffer
|
// Copy a snapshot of the current stack state to a new buffer
|
||||||
if !l.cfg.DisableStack {
|
if !l.cfg.DisableStack {
|
||||||
structlog.Stack = append(structlog.Stack, stack.Data()...)
|
structLog.Stack = append(structLog.Stack, stack.Data()...)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
recordStorageDetail bool
|
recordStorageDetail bool
|
||||||
|
|
@ -262,20 +250,20 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
||||||
l.storage[contractAddress] = make(Storage)
|
l.storage[contractAddress] = make(Storage)
|
||||||
}
|
}
|
||||||
l.storage[contractAddress][storageKey] = storageValue
|
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)
|
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.cfg.EnableReturnData {
|
if l.cfg.EnableReturnData {
|
||||||
structlog.ReturnData.Write(rData)
|
structLog.ReturnData.Write(rData)
|
||||||
}
|
}
|
||||||
execFuncList, ok := OpcodeExecs[op]
|
execFuncList, ok := OpcodeExecs[op]
|
||||||
if ok {
|
if ok {
|
||||||
// execute trace func list.
|
// execute trace func list.
|
||||||
for _, exec := range execFuncList {
|
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)
|
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -283,12 +271,12 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
||||||
// for each "calling" op, pick the caller's state
|
// for each "calling" op, pick the caller's state
|
||||||
switch op {
|
switch op {
|
||||||
case CALL, CALLCODE, STATICCALL, DELEGATECALL, CREATE, CREATE2:
|
case CALL, CALLCODE, STATICCALL, DELEGATECALL, CREATE, CREATE2:
|
||||||
extraData := structlog.getOrInitExtraData()
|
extraData := structLog.getOrInitExtraData()
|
||||||
extraData.Caller = append(extraData.Caller, getWrappedAccountForAddr(l, scope.Contract.Address()))
|
extraData.Caller = append(extraData.Caller, getWrappedAccountForAddr(l, scope.Contract.Address()))
|
||||||
}
|
}
|
||||||
|
|
||||||
structlog.RefundCounter = l.env.StateDB.GetRefund()
|
structLog.RefundCounter = l.env.StateDB.GetRefund()
|
||||||
l.logs = append(l.logs, structlog)
|
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) {
|
func (l *StructLogger) CaptureStateAfter(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
||||||
|
|
@ -335,7 +323,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) {
|
func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
stackH := len(l.callStackLogInd)
|
stackH := len(l.callStackLogInd)
|
||||||
if stackH == 0 {
|
if stackH == 0 {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 3 // Major version component of the current release
|
VersionMajor = 3 // Major version component of the current release
|
||||||
VersionMinor = 1 // Minor 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
|
VersionMeta = "alpha" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue