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
Jul 01, 2021
by
Martin Holst Swende
Committed by
GitHub
Jul 01, 2021
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
Show 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
...
@@ -4,11 +4,11 @@ package vm
import
(
import
(
"encoding/json"
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/math"
"github.com/holiman/uint256"
)
)
var
_
=
(
*
structLogMarshaling
)(
nil
)
var
_
=
(
*
structLogMarshaling
)(
nil
)
...
@@ -22,8 +22,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
...
@@ -22,8 +22,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
GasCost
math
.
HexOrDecimal64
`json:"gasCost"`
GasCost
math
.
HexOrDecimal64
`json:"gasCost"`
Memory
hexutil
.
Bytes
`json:"memory"`
Memory
hexutil
.
Bytes
`json:"memory"`
MemorySize
int
`json:"memSize"`
MemorySize
int
`json:"memSize"`
Stack
[]
*
math
.
HexOrDecimal256
`json:"stack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnStack
[]
math
.
HexOrDecimal64
`json:"returnStack"`
ReturnData
hexutil
.
Bytes
`json:"returnData"`
ReturnData
hexutil
.
Bytes
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
int
`json:"depth"`
Depth
int
`json:"depth"`
...
@@ -39,12 +38,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
...
@@ -39,12 +38,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
enc
.
GasCost
=
math
.
HexOrDecimal64
(
s
.
GasCost
)
enc
.
GasCost
=
math
.
HexOrDecimal64
(
s
.
GasCost
)
enc
.
Memory
=
s
.
Memory
enc
.
Memory
=
s
.
Memory
enc
.
MemorySize
=
s
.
MemorySize
enc
.
MemorySize
=
s
.
MemorySize
if
s
.
Stack
!=
nil
{
enc
.
Stack
=
s
.
Stack
enc
.
Stack
=
make
([]
*
math
.
HexOrDecimal256
,
len
(
s
.
Stack
))
for
k
,
v
:=
range
s
.
Stack
{
enc
.
Stack
[
k
]
=
(
*
math
.
HexOrDecimal256
)(
v
)
}
}
enc
.
ReturnData
=
s
.
ReturnData
enc
.
ReturnData
=
s
.
ReturnData
enc
.
Storage
=
s
.
Storage
enc
.
Storage
=
s
.
Storage
enc
.
Depth
=
s
.
Depth
enc
.
Depth
=
s
.
Depth
...
@@ -64,7 +58,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
...
@@ -64,7 +58,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
GasCost
*
math
.
HexOrDecimal64
`json:"gasCost"`
GasCost
*
math
.
HexOrDecimal64
`json:"gasCost"`
Memory
*
hexutil
.
Bytes
`json:"memory"`
Memory
*
hexutil
.
Bytes
`json:"memory"`
MemorySize
*
int
`json:"memSize"`
MemorySize
*
int
`json:"memSize"`
Stack
[]
*
math
.
HexOrDecimal256
`json:"stack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnData
*
hexutil
.
Bytes
`json:"returnData"`
ReturnData
*
hexutil
.
Bytes
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
*
int
`json:"depth"`
Depth
*
int
`json:"depth"`
...
@@ -94,10 +88,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
...
@@ -94,10 +88,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s
.
MemorySize
=
*
dec
.
MemorySize
s
.
MemorySize
=
*
dec
.
MemorySize
}
}
if
dec
.
Stack
!=
nil
{
if
dec
.
Stack
!=
nil
{
s
.
Stack
=
make
([]
*
big
.
Int
,
len
(
dec
.
Stack
))
s
.
Stack
=
dec
.
Stack
for
k
,
v
:=
range
dec
.
Stack
{
s
.
Stack
[
k
]
=
(
*
big
.
Int
)(
v
)
}
}
}
if
dec
.
ReturnData
!=
nil
{
if
dec
.
ReturnData
!=
nil
{
s
.
ReturnData
=
*
dec
.
ReturnData
s
.
ReturnData
=
*
dec
.
ReturnData
...
...
core/vm/logger.go
View file @
f5f906dd
...
@@ -29,6 +29,7 @@ import (
...
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
)
// Storage represents a contract's storage.
// Storage represents a contract's storage.
...
@@ -66,7 +67,7 @@ type StructLog struct {
...
@@ -66,7 +67,7 @@ type StructLog struct {
GasCost
uint64
`json:"gasCost"`
GasCost
uint64
`json:"gasCost"`
Memory
[]
byte
`json:"memory"`
Memory
[]
byte
`json:"memory"`
MemorySize
int
`json:"memSize"`
MemorySize
int
`json:"memSize"`
Stack
[]
*
big
.
Int
`json:"stack"`
Stack
[]
uint256
.
Int
`json:"stack"`
ReturnData
[]
byte
`json:"returnData"`
ReturnData
[]
byte
`json:"returnData"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Storage
map
[
common
.
Hash
]
common
.
Hash
`json:"-"`
Depth
int
`json:"depth"`
Depth
int
`json:"depth"`
...
@@ -76,7 +77,6 @@ type StructLog struct {
...
@@ -76,7 +77,6 @@ type StructLog struct {
// overrides for gencodec
// overrides for gencodec
type
structLogMarshaling
struct
{
type
structLogMarshaling
struct
{
Stack
[]
*
math
.
HexOrDecimal256
Gas
math
.
HexOrDecimal64
Gas
math
.
HexOrDecimal64
GasCost
math
.
HexOrDecimal64
GasCost
math
.
HexOrDecimal64
Memory
hexutil
.
Bytes
Memory
hexutil
.
Bytes
...
@@ -135,6 +135,14 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
...
@@ -135,6 +135,14 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
return
logger
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.
// 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
)
{
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
...
@@ -157,16 +165,16 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
copy
(
mem
,
memory
.
Data
())
copy
(
mem
,
memory
.
Data
())
}
}
// 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
[]
*
big
.
Int
var
stck
[]
uint256
.
Int
if
!
l
.
cfg
.
DisableStack
{
if
!
l
.
cfg
.
DisableStack
{
stck
=
make
([]
*
big
.
Int
,
len
(
stack
.
Data
()))
stck
=
make
([]
uint256
.
Int
,
len
(
stack
.
Data
()))
for
i
,
item
:=
range
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
// Copy a snapshot of the current storage to a new container
var
storage
Storage
var
storage
Storage
if
!
l
.
cfg
.
DisableStorage
{
if
!
l
.
cfg
.
DisableStorage
&&
(
op
==
SLOAD
||
op
==
SSTORE
)
{
// initialise new changed values storage container for this contract
// initialise new changed values storage container for this contract
// if not present.
// if not present.
if
l
.
storage
[
contract
.
Address
()]
==
nil
{
if
l
.
storage
[
contract
.
Address
()]
==
nil
{
...
@@ -179,17 +187,17 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
...
@@ -179,17 +187,17 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
value
=
env
.
StateDB
.
GetState
(
contract
.
Address
(),
address
)
value
=
env
.
StateDB
.
GetState
(
contract
.
Address
(),
address
)
)
)
l
.
storage
[
contract
.
Address
()][
address
]
=
value
l
.
storage
[
contract
.
Address
()][
address
]
=
value
}
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.
// capture SSTORE opcodes and record the written entry in the local storage.
if
op
==
SSTORE
&&
stack
.
len
()
>=
2
{
var
(
var
(
value
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
2
]
.
Bytes32
())
value
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
2
]
.
Bytes32
())
address
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
1
]
.
Bytes32
())
address
=
common
.
Hash
(
stack
.
data
[
stack
.
len
()
-
1
]
.
Bytes32
())
)
)
l
.
storage
[
contract
.
Address
()][
address
]
=
value
l
.
storage
[
contract
.
Address
()][
address
]
=
value
}
storage
=
l
.
storage
[
contract
.
Address
()]
.
Copy
()
storage
=
l
.
storage
[
contract
.
Address
()]
.
Copy
()
}
}
}
var
rdata
[]
byte
var
rdata
[]
byte
if
!
l
.
cfg
.
DisableReturnData
{
if
!
l
.
cfg
.
DisableReturnData
{
rdata
=
make
([]
byte
,
len
(
rData
))
rdata
=
make
([]
byte
,
len
(
rData
))
...
@@ -238,7 +246,7 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
...
@@ -238,7 +246,7 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
if
len
(
log
.
Stack
)
>
0
{
if
len
(
log
.
Stack
)
>
0
{
fmt
.
Fprintln
(
writer
,
"Stack:"
)
fmt
.
Fprintln
(
writer
,
"Stack:"
)
for
i
:=
len
(
log
.
Stack
)
-
1
;
i
>=
0
;
i
--
{
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
{
if
len
(
log
.
Memory
)
>
0
{
...
@@ -314,7 +322,7 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
...
@@ -314,7 +322,7 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
// format stack
// format stack
var
a
[]
string
var
a
[]
string
for
_
,
elem
:=
range
stack
.
data
{
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
,
","
))
b
:=
fmt
.
Sprintf
(
"[%v]"
,
strings
.
Join
(
a
,
","
))
fmt
.
Fprintf
(
t
.
out
,
"%10v |"
,
b
)
fmt
.
Fprintf
(
t
.
out
,
"%10v |"
,
b
)
...
...
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
...
@@ -57,7 +57,6 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
Gas
:
gas
,
Gas
:
gas
,
GasCost
:
cost
,
GasCost
:
cost
,
MemorySize
:
memory
.
Len
(),
MemorySize
:
memory
.
Len
(),
Storage
:
nil
,
Depth
:
depth
,
Depth
:
depth
,
RefundCounter
:
env
.
StateDB
.
GetRefund
(),
RefundCounter
:
env
.
StateDB
.
GetRefund
(),
Err
:
err
,
Err
:
err
,
...
@@ -66,12 +65,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
...
@@ -66,12 +65,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
log
.
Memory
=
memory
.
Data
()
log
.
Memory
=
memory
.
Data
()
}
}
if
!
l
.
cfg
.
DisableStack
{
if
!
l
.
cfg
.
DisableStack
{
//TODO(@holiman) improve this
log
.
Stack
=
stack
.
data
logstack
:=
make
([]
*
big
.
Int
,
len
(
stack
.
Data
()))
for
i
,
item
:=
range
stack
.
Data
()
{
logstack
[
i
]
=
item
.
ToBig
()
}
log
.
Stack
=
logstack
}
}
if
!
l
.
cfg
.
DisableReturnData
{
if
!
l
.
cfg
.
DisableReturnData
{
log
.
ReturnData
=
rData
log
.
ReturnData
=
rData
...
...
eth/tracers/tracers_test.go
View file @
f5f906dd
...
@@ -300,3 +300,81 @@ func jsonEqual(x, y interface{}) bool {
...
@@ -300,3 +300,81 @@ func jsonEqual(x, y interface{}) bool {
}
}
return
reflect
.
DeepEqual
(
xTrace
,
yTrace
)
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
()
}
}
internal/ethapi/api.go
View file @
f5f906dd
...
@@ -1117,7 +1117,7 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
...
@@ -1117,7 +1117,7 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
if
trace
.
Stack
!=
nil
{
if
trace
.
Stack
!=
nil
{
stack
:=
make
([]
string
,
len
(
trace
.
Stack
))
stack
:=
make
([]
string
,
len
(
trace
.
Stack
))
for
i
,
stackValue
:=
range
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
formatted
[
index
]
.
Stack
=
&
stack
}
}
...
...
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