Skip to content

Commit

Permalink
refactor: optimize and improve tps for contract call. (#83)
Browse files Browse the repository at this point in the history
* upgrade block trace

* upgrade block trace

* Correct comments
  • Loading branch information
mask-pp authored May 4, 2022
1 parent c180aa2 commit a79e72f
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 35 deletions.
5 changes: 5 additions & 0 deletions core/types/l2trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ func NewExtraData() *ExtraData {
}
}

func (e *ExtraData) Clean() {
e.CodeList = e.CodeList[:0]
e.ProofList = e.ProofList[:0]
}

// SealExtraData doesn't show empty fields.
func (e *ExtraData) SealExtraData() *ExtraData {
if len(e.CodeList) == 0 {
Expand Down
8 changes: 4 additions & 4 deletions core/vm/gen_structlog.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 56 additions & 29 deletions core/vm/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
package vm

import (
"bytes"
"encoding/hex"
"fmt"
"io"
"math/big"
"runtime"
"strings"
"sync"
"time"

"github.com/holiman/uint256"
Expand Down Expand Up @@ -67,17 +70,48 @@ type StructLog struct {
Op OpCode `json:"op"`
Gas uint64 `json:"gas"`
GasCost uint64 `json:"gasCost"`
Memory []byte `json:"memory"`
Memory bytes.Buffer `json:"memory"`
MemorySize int `json:"memSize"`
Stack []uint256.Int `json:"stack"`
ReturnData []byte `json:"returnData"`
ReturnData bytes.Buffer `json:"returnData"`
Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"`
RefundCounter uint64 `json:"refund"`
ExtraData *types.ExtraData `json:"extraData"`
Err error `json:"-"`
}

var (
loggerPool = sync.Pool{
New: func() interface{} {
return &StructLog{
Stack: make([]uint256.Int, 0),
ExtraData: types.NewExtraData(),
}
},
}
)

func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int) *StructLog {

structlog := loggerPool.Get().(*StructLog)
structlog.Pc, structlog.Op, structlog.Gas, structlog.GasCost, structlog.Depth = pc, op, gas, cost, depth

runtime.SetFinalizer(structlog, func(logger *StructLog) {
logger.clean()
loggerPool.Put(logger)
})
return structlog
}

func (s *StructLog) clean() {
s.Memory.Reset()
s.Stack = s.Stack[:0]
s.ReturnData.Reset()
s.Storage = nil
s.ExtraData.Clean()
}

// overrides for gencodec
type structLogMarshaling struct {
Gas math.HexOrDecimal64
Expand Down Expand Up @@ -162,27 +196,24 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
memory := scope.Memory
stack := scope.Stack
contract := scope.Contract
// create a struct log.
structlog := NewStructlog(pc, op, gas, cost, depth)

// check if already accumulated the specified number of logs
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
return
}
// Copy a snapshot of the current memory state to a new buffer
var mem []byte
if l.cfg.EnableMemory {
mem = make([]byte, len(memory.Data()))
copy(mem, memory.Data())
structlog.Memory.Write(memory.Data())
structlog.MemorySize = memory.Len()
}
// Copy a snapshot of the current stack state to a new buffer
var stck []uint256.Int
if !l.cfg.DisableStack {
stck = make([]uint256.Int, len(stack.Data()))
for i, item := range stack.Data() {
stck[i] = item
}
structlog.Stack = append(structlog.Stack, stack.Data()...)
}
var (
recordStorageDetail bool
storage Storage
storageKey common.Hash
storageValue common.Hash
)
Expand All @@ -197,37 +228,33 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
storageValue = stack.data[stack.len()-2].Bytes32()
}
}
extraData := types.NewExtraData()
if recordStorageDetail {
contractAddress := contract.Address()
if l.storage[contractAddress] == nil {
l.storage[contractAddress] = make(Storage)
}
l.storage[contractAddress][storageKey] = storageValue
storage = l.storage[contractAddress].Copy()
structlog.Storage = l.storage[contractAddress].Copy()

if err := traceStorageProof(l, scope, extraData); err != nil {
if err := traceStorageProof(l, scope, structlog.ExtraData); err != nil {
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
}
}
var rdata []byte
if l.cfg.EnableReturnData {
rdata = make([]byte, len(rData))
copy(rdata, rData)
structlog.ReturnData.Write(rData)
}
execFuncList, ok := OpcodeExecs[op]
if ok {
// execute trace func list.
for _, exec := range execFuncList {
if err = exec(l, scope, extraData); err != nil {
if err = exec(l, scope, structlog.ExtraData); err != nil {
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
}
}
}

// create a new snapshot of the EVM.
structLog := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), extraData, err}
l.logs = append(l.logs, structLog)
structlog.RefundCounter, structlog.Err = l.env.StateDB.GetRefund(), err
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) {
Expand Down Expand Up @@ -309,19 +336,19 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
fmt.Fprintf(writer, "%08d %s\n", len(log.Stack)-i-1, log.Stack[i].Hex())
}
}
if len(log.Memory) > 0 {
if log.Memory.Len() > 0 {
fmt.Fprintln(writer, "Memory:")
fmt.Fprint(writer, hex.Dump(log.Memory))
fmt.Fprint(writer, hex.Dump(log.Memory.Bytes()))
}
if len(log.Storage) > 0 {
fmt.Fprintln(writer, "Storage:")
for h, item := range log.Storage {
fmt.Fprintf(writer, "%x: %x\n", h, item)
}
}
if len(log.ReturnData) > 0 {
if log.ReturnData.Len() > 0 {
fmt.Fprintln(writer, "ReturnData:")
fmt.Fprint(writer, hex.Dump(log.ReturnData))
fmt.Fprint(writer, hex.Dump(log.ReturnData.Bytes()))
}
fmt.Fprintln(writer)
}
Expand Down Expand Up @@ -434,10 +461,10 @@ func FormatLogs(logs []StructLog) []types.StructLogRes {
}
formatted[index].Stack = &stack
}
if len(trace.Memory) != 0 {
memory := make([]string, 0, (len(trace.Memory)+31)/32)
for i := 0; i+32 <= len(trace.Memory); i += 32 {
memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
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]))
}
formatted[index].Memory = &memory
}
Expand Down
4 changes: 2 additions & 2 deletions core/vm/logger_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ func (l *JSONLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope
Err: err,
}
if l.cfg.EnableMemory {
log.Memory = memory.Data()
log.Memory.Write(memory.Data())
}
if !l.cfg.DisableStack {
log.Stack = stack.data
}
if l.cfg.EnableReturnData {
log.ReturnData = rData
log.ReturnData.Write(rData)
}
l.encoder.Encode(log)
}
Expand Down

0 comments on commit a79e72f

Please sign in to comment.