Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
f5f906dd
Unverified
Commit
f5f906dd
authored
3 years ago
by
Martin Holst Swende
Committed by
GitHub
3 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth/tracers: improve tracing performance (#23016)
Improves the performance of debug.traceTransaction
parent
bbbeb7d8
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
105 additions
and
34 deletions
+105
-34
gen_structlog.go
core/vm/gen_structlog.go
+5
-14
logger.go
core/vm/logger.go
+20
-12
logger_json.go
core/vm/logger_json.go
+1
-7
tracers_test.go
eth/tracers/tracers_test.go
+78
-0
api.go
internal/ethapi/api.go
+1
-1
No files found.
core/vm/gen_structlog.go
View file @
f5f906dd
...
...
@@ -4,11 +4,11 @@ package vm
import
(
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/holiman/uint256"
)
var
_
=
(
*
structLogMarshaling
)(
nil
)
...
...
@@ -22,8 +22,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
GasCost
math
.
HexOrDecimal64
`json:"gasCost"`
Memory
hexutil
.
Bytes
`json:"memory"`
MemorySize
int
`json:"memSize"`
Stack
[]
*
math
.
HexOrDecimal256
`json:"stack"`
ReturnStack
[]
math
.
HexOrDecimal64
`json:"returnStack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnData
hexutil
.
Bytes
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
int
`json:"depth"`
...
...
@@ -39,12 +38,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
enc
.
GasCost
=
math
.
HexOrDecimal64
(
s
.
GasCost
)
enc
.
Memory
=
s
.
Memory
enc
.
MemorySize
=
s
.
MemorySize
if
s
.
Stack
!=
nil
{
enc
.
Stack
=
make
([]
*
math
.
HexOrDecimal256
,
len
(
s
.
Stack
))
for
k
,
v
:=
range
s
.
Stack
{
enc
.
Stack
[
k
]
=
(
*
math
.
HexOrDecimal256
)(
v
)
}
}
enc
.
Stack
=
s
.
Stack
enc
.
ReturnData
=
s
.
ReturnData
enc
.
Storage
=
s
.
Storage
enc
.
Depth
=
s
.
Depth
...
...
@@ -64,7 +58,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
GasCost
*
math
.
HexOrDecimal64
`json:"gasCost"`
Memory
*
hexutil
.
Bytes
`json:"memory"`
MemorySize
*
int
`json:"memSize"`
Stack
[]
*
math
.
HexOrDecimal256
`json:"stack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnData
*
hexutil
.
Bytes
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
*
int
`json:"depth"`
...
...
@@ -94,10 +88,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s
.
MemorySize
=
*
dec
.
MemorySize
}
if
dec
.
Stack
!=
nil
{
s
.
Stack
=
make
([]
*
big
.
Int
,
len
(
dec
.
Stack
))
for
k
,
v
:=
range
dec
.
Stack
{
s
.
Stack
[
k
]
=
(
*
big
.
Int
)(
v
)
}
s
.
Stack
=
dec
.
Stack
}
if
dec
.
ReturnData
!=
nil
{
s
.
ReturnData
=
*
dec
.
ReturnData
...
...
This diff is collapsed.
Click to expand it.
core/vm/logger.go
View file @
f5f906dd
...
...
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
// Storage represents a contract's storage.
...
...
@@ -66,7 +67,7 @@ type StructLog struct {
GasCost
uint64
`json:"gasCost"`
Memory
[]
byte
`json:"memory"`
MemorySize
int
`json:"memSize"`
Stack
[]
*
big
.
Int
`json:"stack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnData
[]
byte
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
int
`json:"depth"`
...
...
@@ -76,7 +77,6 @@ type StructLog struct {
// overrides for gencodec
type
structLogMarshaling
struct
{
Stack
[]
*
math
.
HexOrDecimal256
Gas
math
.
HexOrDecimal64
GasCost
math
.
HexOrDecimal64
Memory
hexutil
.
Bytes
...
...
@@ -135,6 +135,14 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
return
logger
}
// Reset clears the data held by the logger.
func
(
l
*
StructLogger
)
Reset
()
{
l
.
storage
=
make
(
map
[
common
.
Address
]
Storage
)
l
.
output
=
make
([]
byte
,
0
)
l
.
logs
=
l
.
logs
[
:
0
]
l
.
err
=
nil
}
// CaptureStart implements the Tracer interface to initialize the tracing operation.
func
(
l
*
StructLogger
)
CaptureStart
(
env
*
EVM
,
from
common
.
Address
,
to
common
.
Address
,
create
bool
,
input
[]
byte
,
gas
uint64
,
value
*
big
.
Int
)
{
}
...
...
@@ -157,16 +165,16 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
copy
(
mem
,
memory
.
Data
())
}
// Copy a snapshot of the current stack state to a new buffer
var
stck
[]
*
big
.
Int
var
stck
[]
uint256
.
Int
if
!
l
.
cfg
.
DisableStack
{
stck
=
make
([]
*
big
.
Int
,
len
(
stack
.
Data
()))
stck
=
make
([]
uint256
.
Int
,
len
(
stack
.
Data
()))
for
i
,
item
:=
range
stack
.
Data
()
{
stck
[
i
]
=
new
(
big
.
Int
)
.
Set
(
item
.
ToBig
())
stck
[
i
]
=
item
}
}
// Copy a snapshot of the current storage to a new container
var
storage
Storage
if
!
l
.
cfg
.
DisableStorage
{
if
!
l
.
cfg
.
DisableStorage
&&
(
op
==
SLOAD
||
op
==
SSTORE
)
{
// initialise new changed values storage container for this contract
// if not present.
if
l
.
storage
[
contract
.
Address
()]
==
nil
{
...
...
@@ -179,16 +187,16 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
value
=
env
.
StateDB
.
GetState
(
contract
.
Address
(),
address
)
)
l
.
storage
[
contract
.
Address
()][
address
]
=
value
}
// capture SSTORE opcodes and record the written entry in the local storage.
if
op
==
SSTORE
&&
stack
.
len
()
>=
2
{
storage
=
l
.
storage
[
contract
.
Address
()]
.
Copy
()
}
else
if
op
==
SSTORE
&&
stack
.
len
()
>=
2
{
// capture SSTORE opcodes and record the written entry in the local storage.
var
(
value
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
2
]
.
Bytes32
())
address
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
1
]
.
Bytes32
())
)
l
.
storage
[
contract
.
Address
()][
address
]
=
value
storage
=
l
.
storage
[
contract
.
Address
()]
.
Copy
()
}
storage
=
l
.
storage
[
contract
.
Address
()]
.
Copy
()
}
var
rdata
[]
byte
if
!
l
.
cfg
.
DisableReturnData
{
...
...
@@ -238,7 +246,7 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
if
len
(
log
.
Stack
)
>
0
{
fmt
.
Fprintln
(
writer
,
"Stack:"
)
for
i
:=
len
(
log
.
Stack
)
-
1
;
i
>=
0
;
i
--
{
fmt
.
Fprintf
(
writer
,
"%08d %
x
\n
"
,
len
(
log
.
Stack
)
-
i
-
1
,
math
.
PaddedBigBytes
(
log
.
Stack
[
i
],
32
))
fmt
.
Fprintf
(
writer
,
"%08d %
s
\n
"
,
len
(
log
.
Stack
)
-
i
-
1
,
log
.
Stack
[
i
]
.
Hex
(
))
}
}
if
len
(
log
.
Memory
)
>
0
{
...
...
@@ -314,7 +322,7 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
// format stack
var
a
[]
string
for
_
,
elem
:=
range
stack
.
data
{
a
=
append
(
a
,
fmt
.
Sprintf
(
"%v"
,
elem
.
String
()
))
a
=
append
(
a
,
elem
.
Hex
(
))
}
b
:=
fmt
.
Sprintf
(
"[%v]"
,
strings
.
Join
(
a
,
","
))
fmt
.
Fprintf
(
t
.
out
,
"%10v |"
,
b
)
...
...
This diff is collapsed.
Click to expand it.
core/vm/logger_json.go
View file @
f5f906dd
...
...
@@ -57,7 +57,6 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
Gas
:
gas
,
GasCost
:
cost
,
MemorySize
:
memory
.
Len
(),
Storage
:
nil
,
Depth
:
depth
,
RefundCounter
:
env
.
StateDB
.
GetRefund
(),
Err
:
err
,
...
...
@@ -66,12 +65,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
log
.
Memory
=
memory
.
Data
()
}
if
!
l
.
cfg
.
DisableStack
{
//TODO(@holiman) improve this
logstack
:=
make
([]
*
big
.
Int
,
len
(
stack
.
Data
()))
for
i
,
item
:=
range
stack
.
Data
()
{
logstack
[
i
]
=
item
.
ToBig
()
}
log
.
Stack
=
logstack
log
.
Stack
=
stack
.
data
}
if
!
l
.
cfg
.
DisableReturnData
{
log
.
ReturnData
=
rData
...
...
This diff is collapsed.
Click to expand it.
eth/tracers/tracers_test.go
View file @
f5f906dd
...
...
@@ -300,3 +300,81 @@ func jsonEqual(x, y interface{}) bool {
}
return
reflect
.
DeepEqual
(
xTrace
,
yTrace
)
}
func
BenchmarkTransactionTrace
(
b
*
testing
.
B
)
{
key
,
_
:=
crypto
.
HexToECDSA
(
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
)
from
:=
crypto
.
PubkeyToAddress
(
key
.
PublicKey
)
gas
:=
uint64
(
1000000
)
// 1M gas
to
:=
common
.
HexToAddress
(
"0x00000000000000000000000000000000deadbeef"
)
signer
:=
types
.
LatestSignerForChainID
(
big
.
NewInt
(
1337
))
tx
,
err
:=
types
.
SignNewTx
(
key
,
signer
,
&
types
.
LegacyTx
{
Nonce
:
1
,
GasPrice
:
big
.
NewInt
(
500
),
Gas
:
gas
,
To
:
&
to
,
})
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
txContext
:=
vm
.
TxContext
{
Origin
:
from
,
GasPrice
:
tx
.
GasPrice
(),
}
context
:=
vm
.
BlockContext
{
CanTransfer
:
core
.
CanTransfer
,
Transfer
:
core
.
Transfer
,
Coinbase
:
common
.
Address
{},
BlockNumber
:
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
5
)),
Time
:
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
5
)),
Difficulty
:
big
.
NewInt
(
0xffffffff
),
GasLimit
:
gas
,
}
alloc
:=
core
.
GenesisAlloc
{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
// the address
loop
:=
[]
byte
{
byte
(
vm
.
JUMPDEST
),
// [ count ]
byte
(
vm
.
PUSH1
),
0
,
// jumpdestination
byte
(
vm
.
JUMP
),
}
alloc
[
common
.
HexToAddress
(
"0x00000000000000000000000000000000deadbeef"
)]
=
core
.
GenesisAccount
{
Nonce
:
1
,
Code
:
loop
,
Balance
:
big
.
NewInt
(
1
),
}
alloc
[
from
]
=
core
.
GenesisAccount
{
Nonce
:
1
,
Code
:
[]
byte
{},
Balance
:
big
.
NewInt
(
500000000000000
),
}
_
,
statedb
:=
tests
.
MakePreState
(
rawdb
.
NewMemoryDatabase
(),
alloc
,
false
)
// Create the tracer, the EVM environment and run it
tracer
:=
vm
.
NewStructLogger
(
&
vm
.
LogConfig
{
Debug
:
false
,
//DisableStorage: true,
//DisableMemory: true,
//DisableReturnData: true,
})
evm
:=
vm
.
NewEVM
(
context
,
txContext
,
statedb
,
params
.
AllEthashProtocolChanges
,
vm
.
Config
{
Debug
:
true
,
Tracer
:
tracer
})
msg
,
err
:=
tx
.
AsMessage
(
signer
,
nil
)
if
err
!=
nil
{
b
.
Fatalf
(
"failed to prepare transaction for tracing: %v"
,
err
)
}
b
.
ResetTimer
()
b
.
ReportAllocs
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
snap
:=
statedb
.
Snapshot
()
st
:=
core
.
NewStateTransition
(
evm
,
msg
,
new
(
core
.
GasPool
)
.
AddGas
(
tx
.
Gas
()))
_
,
err
=
st
.
TransitionDb
()
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
statedb
.
RevertToSnapshot
(
snap
)
if
have
,
want
:=
len
(
tracer
.
StructLogs
()),
244752
;
have
!=
want
{
b
.
Fatalf
(
"trace wrong, want %d steps, have %d"
,
want
,
have
)
}
tracer
.
Reset
()
}
}
This diff is collapsed.
Click to expand it.
internal/ethapi/api.go
View file @
f5f906dd
...
...
@@ -1117,7 +1117,7 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
if
trace
.
Stack
!=
nil
{
stack
:=
make
([]
string
,
len
(
trace
.
Stack
))
for
i
,
stackValue
:=
range
trace
.
Stack
{
stack
[
i
]
=
fmt
.
Sprintf
(
"%x"
,
math
.
PaddedBigBytes
(
stackValue
,
32
)
)
stack
[
i
]
=
stackValue
.
Hex
(
)
}
formatted
[
index
]
.
Stack
=
&
stack
}
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment