mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
refactor: optimize and improve tps for contract call. (#83)
* upgrade block trace * upgrade block trace * Correct comments
This commit is contained in:
parent
c180aa2e75
commit
a79e72f697
4 changed files with 67 additions and 35 deletions
|
|
@ -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.
|
// SealExtraData doesn't show empty fields.
|
||||||
func (e *ExtraData) SealExtraData() *ExtraData {
|
func (e *ExtraData) SealExtraData() *ExtraData {
|
||||||
if len(e.CodeList) == 0 {
|
if len(e.CodeList) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
|
||||||
enc.Op = s.Op
|
enc.Op = s.Op
|
||||||
enc.Gas = math.HexOrDecimal64(s.Gas)
|
enc.Gas = math.HexOrDecimal64(s.Gas)
|
||||||
enc.GasCost = math.HexOrDecimal64(s.GasCost)
|
enc.GasCost = math.HexOrDecimal64(s.GasCost)
|
||||||
enc.Memory = s.Memory
|
enc.Memory = s.Memory.Bytes()
|
||||||
enc.MemorySize = s.MemorySize
|
enc.MemorySize = s.MemorySize
|
||||||
enc.Stack = s.Stack
|
enc.Stack = s.Stack
|
||||||
enc.ReturnData = s.ReturnData
|
enc.ReturnData = s.ReturnData.Bytes()
|
||||||
enc.Storage = s.Storage
|
enc.Storage = s.Storage
|
||||||
enc.Depth = s.Depth
|
enc.Depth = s.Depth
|
||||||
enc.RefundCounter = s.RefundCounter
|
enc.RefundCounter = s.RefundCounter
|
||||||
|
|
@ -83,7 +83,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
|
||||||
s.GasCost = uint64(*dec.GasCost)
|
s.GasCost = uint64(*dec.GasCost)
|
||||||
}
|
}
|
||||||
if dec.Memory != nil {
|
if dec.Memory != nil {
|
||||||
s.Memory = *dec.Memory
|
s.Memory.Write(*dec.Memory)
|
||||||
}
|
}
|
||||||
if dec.MemorySize != nil {
|
if dec.MemorySize != nil {
|
||||||
s.MemorySize = *dec.MemorySize
|
s.MemorySize = *dec.MemorySize
|
||||||
|
|
@ -92,7 +92,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
|
||||||
s.Stack = dec.Stack
|
s.Stack = dec.Stack
|
||||||
}
|
}
|
||||||
if dec.ReturnData != nil {
|
if dec.ReturnData != nil {
|
||||||
s.ReturnData = *dec.ReturnData
|
s.ReturnData.Write(*dec.ReturnData)
|
||||||
}
|
}
|
||||||
if dec.Storage != nil {
|
if dec.Storage != nil {
|
||||||
s.Storage = dec.Storage
|
s.Storage = dec.Storage
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,14 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -67,10 +70,10 @@ type StructLog struct {
|
||||||
Op OpCode `json:"op"`
|
Op OpCode `json:"op"`
|
||||||
Gas uint64 `json:"gas"`
|
Gas uint64 `json:"gas"`
|
||||||
GasCost uint64 `json:"gasCost"`
|
GasCost uint64 `json:"gasCost"`
|
||||||
Memory []byte `json:"memory"`
|
Memory bytes.Buffer `json:"memory"`
|
||||||
MemorySize int `json:"memSize"`
|
MemorySize int `json:"memSize"`
|
||||||
Stack []uint256.Int `json:"stack"`
|
Stack []uint256.Int `json:"stack"`
|
||||||
ReturnData []byte `json:"returnData"`
|
ReturnData bytes.Buffer `json:"returnData"`
|
||||||
Storage map[common.Hash]common.Hash `json:"-"`
|
Storage map[common.Hash]common.Hash `json:"-"`
|
||||||
Depth int `json:"depth"`
|
Depth int `json:"depth"`
|
||||||
RefundCounter uint64 `json:"refund"`
|
RefundCounter uint64 `json:"refund"`
|
||||||
|
|
@ -78,6 +81,37 @@ type StructLog struct {
|
||||||
Err error `json:"-"`
|
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
|
// overrides for gencodec
|
||||||
type structLogMarshaling struct {
|
type structLogMarshaling struct {
|
||||||
Gas math.HexOrDecimal64
|
Gas math.HexOrDecimal64
|
||||||
|
|
@ -162,27 +196,24 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
||||||
memory := scope.Memory
|
memory := scope.Memory
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
contract := scope.Contract
|
contract := scope.Contract
|
||||||
|
// create a struct log.
|
||||||
|
structlog := NewStructlog(pc, op, gas, cost, depth)
|
||||||
|
|
||||||
// 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) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Copy a snapshot of the current memory state to a new buffer
|
// Copy a snapshot of the current memory state to a new buffer
|
||||||
var mem []byte
|
|
||||||
if l.cfg.EnableMemory {
|
if l.cfg.EnableMemory {
|
||||||
mem = make([]byte, len(memory.Data()))
|
structlog.Memory.Write(memory.Data())
|
||||||
copy(mem, memory.Data())
|
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
|
||||||
var stck []uint256.Int
|
|
||||||
if !l.cfg.DisableStack {
|
if !l.cfg.DisableStack {
|
||||||
stck = make([]uint256.Int, len(stack.Data()))
|
structlog.Stack = append(structlog.Stack, stack.Data()...)
|
||||||
for i, item := range stack.Data() {
|
|
||||||
stck[i] = item
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
recordStorageDetail bool
|
recordStorageDetail bool
|
||||||
storage Storage
|
|
||||||
storageKey common.Hash
|
storageKey common.Hash
|
||||||
storageValue common.Hash
|
storageValue common.Hash
|
||||||
)
|
)
|
||||||
|
|
@ -197,37 +228,33 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
||||||
storageValue = stack.data[stack.len()-2].Bytes32()
|
storageValue = stack.data[stack.len()-2].Bytes32()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extraData := types.NewExtraData()
|
|
||||||
if recordStorageDetail {
|
if recordStorageDetail {
|
||||||
contractAddress := contract.Address()
|
contractAddress := contract.Address()
|
||||||
if l.storage[contractAddress] == nil {
|
if l.storage[contractAddress] == nil {
|
||||||
l.storage[contractAddress] = make(Storage)
|
l.storage[contractAddress] = make(Storage)
|
||||||
}
|
}
|
||||||
l.storage[contractAddress][storageKey] = storageValue
|
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)
|
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var rdata []byte
|
|
||||||
if l.cfg.EnableReturnData {
|
if l.cfg.EnableReturnData {
|
||||||
rdata = make([]byte, len(rData))
|
structlog.ReturnData.Write(rData)
|
||||||
copy(rdata, 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, extraData); err != nil {
|
if err = exec(l, scope, structlog.ExtraData); err != nil {
|
||||||
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
|
log.Error("Failed to trace data", "opcode", op.String(), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new snapshot of the EVM.
|
structlog.RefundCounter, structlog.Err = l.env.StateDB.GetRefund(), err
|
||||||
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)
|
||||||
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) {
|
||||||
|
|
@ -309,9 +336,9 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
|
||||||
fmt.Fprintf(writer, "%08d %s\n", len(log.Stack)-i-1, log.Stack[i].Hex())
|
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.Fprintln(writer, "Memory:")
|
||||||
fmt.Fprint(writer, hex.Dump(log.Memory))
|
fmt.Fprint(writer, hex.Dump(log.Memory.Bytes()))
|
||||||
}
|
}
|
||||||
if len(log.Storage) > 0 {
|
if len(log.Storage) > 0 {
|
||||||
fmt.Fprintln(writer, "Storage:")
|
fmt.Fprintln(writer, "Storage:")
|
||||||
|
|
@ -319,9 +346,9 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
|
||||||
fmt.Fprintf(writer, "%x: %x\n", h, item)
|
fmt.Fprintf(writer, "%x: %x\n", h, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(log.ReturnData) > 0 {
|
if log.ReturnData.Len() > 0 {
|
||||||
fmt.Fprintln(writer, "ReturnData:")
|
fmt.Fprintln(writer, "ReturnData:")
|
||||||
fmt.Fprint(writer, hex.Dump(log.ReturnData))
|
fmt.Fprint(writer, hex.Dump(log.ReturnData.Bytes()))
|
||||||
}
|
}
|
||||||
fmt.Fprintln(writer)
|
fmt.Fprintln(writer)
|
||||||
}
|
}
|
||||||
|
|
@ -434,10 +461,10 @@ func FormatLogs(logs []StructLog) []types.StructLogRes {
|
||||||
}
|
}
|
||||||
formatted[index].Stack = &stack
|
formatted[index].Stack = &stack
|
||||||
}
|
}
|
||||||
if len(trace.Memory) != 0 {
|
if trace.Memory.Len() != 0 {
|
||||||
memory := make([]string, 0, (len(trace.Memory)+31)/32)
|
memory := make([]string, 0, (trace.Memory.Len()+31)/32)
|
||||||
for i := 0; i+32 <= len(trace.Memory); i += 32 {
|
for i := 0; i+32 <= trace.Memory.Len(); i += 32 {
|
||||||
memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
|
memory = append(memory, fmt.Sprintf("%x", trace.Memory.Bytes()[i:i+32]))
|
||||||
}
|
}
|
||||||
formatted[index].Memory = &memory
|
formatted[index].Memory = &memory
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,13 @@ func (l *JSONLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
if l.cfg.EnableMemory {
|
if l.cfg.EnableMemory {
|
||||||
log.Memory = memory.Data()
|
log.Memory.Write(memory.Data())
|
||||||
}
|
}
|
||||||
if !l.cfg.DisableStack {
|
if !l.cfg.DisableStack {
|
||||||
log.Stack = stack.data
|
log.Stack = stack.data
|
||||||
}
|
}
|
||||||
if l.cfg.EnableReturnData {
|
if l.cfg.EnableReturnData {
|
||||||
log.ReturnData = rData
|
log.ReturnData.Write(rData)
|
||||||
}
|
}
|
||||||
l.encoder.Encode(log)
|
l.encoder.Encode(log)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue