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
f81cff53
Commit
f81cff53
authored
Aug 22, 2016
by
Péter Szilágyi
Committed by
GitHub
Aug 22, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2923 from Arachnid/tracing
core: Refactor tracing to make Tracer the main interface
parents
37bda7e0
781915f1
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
162 additions
and
282 deletions
+162
-282
main.go
cmd/evm/main.go
+4
-8
environment.go
core/vm/environment.go
+0
-2
gas.go
core/vm/gas.go
+1
-1
instructions.go
core/vm/instructions.go
+73
-73
jit.go
core/vm/jit.go
+3
-3
jit_test.go
core/vm/jit_test.go
+0
-5
logger.go
core/vm/logger.go
+34
-30
logger_test.go
core/vm/logger_test.go
+6
-7
env.go
core/vm/runtime/env.go
+0
-14
segments.go
core/vm/segments.go
+2
-2
stack.go
core/vm/stack.go
+13
-13
vm.go
core/vm/vm.go
+4
-12
vm_env.go
core/vm_env.go
+0
-14
api.go
eth/api.go
+22
-34
api.go
internal/ethapi/api.go
+0
-54
util.go
tests/util.go
+0
-10
No files found.
cmd/evm/main.go
View file @
f81cff53
...
...
@@ -117,10 +117,13 @@ func run(ctx *cli.Context) error {
statedb
,
_
:=
state
.
New
(
common
.
Hash
{},
db
)
sender
:=
statedb
.
CreateAccount
(
common
.
StringToAddress
(
"sender"
))
logger
:=
vm
.
NewStructLogger
(
nil
)
vmenv
:=
NewEnv
(
statedb
,
common
.
StringToAddress
(
"evmuser"
),
common
.
Big
(
ctx
.
GlobalString
(
ValueFlag
.
Name
)),
vm
.
Config
{
Debug
:
ctx
.
GlobalBool
(
DebugFlag
.
Name
),
ForceJit
:
ctx
.
GlobalBool
(
ForceJitFlag
.
Name
),
EnableJit
:
!
ctx
.
GlobalBool
(
DisableJitFlag
.
Name
),
Tracer
:
logger
,
})
tstart
:=
time
.
Now
()
...
...
@@ -157,7 +160,7 @@ func run(ctx *cli.Context) error {
statedb
.
Commit
()
fmt
.
Println
(
string
(
statedb
.
Dump
()))
}
vm
.
StdErrFormat
(
vmenv
.
StructLogs
())
vm
.
StdErrFormat
(
logger
.
StructLogs
())
if
ctx
.
GlobalBool
(
SysStatFlag
.
Name
)
{
var
mem
runtime
.
MemStats
...
...
@@ -209,7 +212,6 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
value
:
value
,
time
:
big
.
NewInt
(
time
.
Now
()
.
Unix
()),
}
cfg
.
Logger
.
Collector
=
env
env
.
evm
=
vm
.
New
(
env
,
cfg
)
return
env
...
...
@@ -242,12 +244,6 @@ func (self *VMEnv) GetHash(n uint64) common.Hash {
}
return
common
.
Hash
{}
}
func
(
self
*
VMEnv
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
func
(
self
*
VMEnv
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
VMEnv
)
AddLog
(
log
*
vm
.
Log
)
{
self
.
state
.
AddLog
(
log
)
}
...
...
core/vm/environment.go
View file @
f81cff53
...
...
@@ -73,8 +73,6 @@ type Environment interface {
DelegateCall
(
me
ContractRef
,
addr
common
.
Address
,
data
[]
byte
,
gas
,
price
*
big
.
Int
)
([]
byte
,
error
)
// Create a new contract
Create
(
me
ContractRef
,
data
[]
byte
,
gas
,
price
,
value
*
big
.
Int
)
([]
byte
,
common
.
Address
,
error
)
StructLogs
()
[]
StructLog
}
// Vm is the basic interface for an implementation of the EVM.
...
...
core/vm/gas.go
View file @
f81cff53
...
...
@@ -38,7 +38,7 @@ var (
)
// baseCheck checks for any stack error underflows
func
baseCheck
(
op
OpCode
,
stack
*
s
tack
,
gas
*
big
.
Int
)
error
{
func
baseCheck
(
op
OpCode
,
stack
*
S
tack
,
gas
*
big
.
Int
)
error
{
// PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
// PUSH is also allowed to calculate the same price for all PUSHes
// DUP requirements are handled elsewhere (except for the stack limit check)
...
...
core/vm/instructions.go
View file @
f81cff53
...
...
@@ -27,14 +27,14 @@ import (
type
programInstruction
interface
{
// executes the program instruction and allows the instruction to modify the state of the program
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
([]
byte
,
error
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
([]
byte
,
error
)
// returns whether the program instruction halts the execution of the JIT
halts
()
bool
// Returns the current op code (debugging purposes)
Op
()
OpCode
}
type
instrFn
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
type
instrFn
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
type
instruction
struct
{
op
OpCode
...
...
@@ -58,7 +58,7 @@ func jump(mapping map[uint64]uint64, destinations map[uint64]struct{}, contract
return
mapping
[
to
.
Uint64
()],
nil
}
func
(
instr
instruction
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
([]
byte
,
error
)
{
func
(
instr
instruction
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
([]
byte
,
error
)
{
// calculate the new memory size and gas price for the current executing opcode
newMemSize
,
cost
,
err
:=
jitCalculateGasAndSize
(
env
,
contract
,
instr
,
env
.
Db
(),
memory
,
stack
)
if
err
!=
nil
{
...
...
@@ -114,26 +114,26 @@ func (instr instruction) Op() OpCode {
return
instr
.
op
}
func
opStaticJump
(
instr
instruction
,
pc
*
uint64
,
ret
*
big
.
Int
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opStaticJump
(
instr
instruction
,
pc
*
uint64
,
ret
*
big
.
Int
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
ret
.
Set
(
instr
.
data
)
}
func
opAdd
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opAdd
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
U256
(
x
.
Add
(
x
,
y
)))
}
func
opSub
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSub
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
U256
(
x
.
Sub
(
x
,
y
)))
}
func
opMul
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMul
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
U256
(
x
.
Mul
(
x
,
y
)))
}
func
opDiv
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opDiv
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
if
y
.
Cmp
(
common
.
Big0
)
!=
0
{
stack
.
push
(
U256
(
x
.
Div
(
x
,
y
)))
...
...
@@ -142,7 +142,7 @@ func opDiv(instr instruction, pc *uint64, env Environment, contract *Contract, m
}
}
func
opSdiv
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSdiv
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
pop
())
if
y
.
Cmp
(
common
.
Big0
)
==
0
{
stack
.
push
(
new
(
big
.
Int
))
...
...
@@ -162,7 +162,7 @@ func opSdiv(instr instruction, pc *uint64, env Environment, contract *Contract,
}
}
func
opMod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
if
y
.
Cmp
(
common
.
Big0
)
==
0
{
stack
.
push
(
new
(
big
.
Int
))
...
...
@@ -171,7 +171,7 @@ func opMod(instr instruction, pc *uint64, env Environment, contract *Contract, m
}
}
func
opSmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
pop
())
if
y
.
Cmp
(
common
.
Big0
)
==
0
{
...
...
@@ -191,12 +191,12 @@ func opSmod(instr instruction, pc *uint64, env Environment, contract *Contract,
}
}
func
opExp
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opExp
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
U256
(
x
.
Exp
(
x
,
y
,
Pow256
)))
}
func
opSignExtend
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSignExtend
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
back
:=
stack
.
pop
()
if
back
.
Cmp
(
big
.
NewInt
(
31
))
<
0
{
bit
:=
uint
(
back
.
Uint64
()
*
8
+
7
)
...
...
@@ -213,12 +213,12 @@ func opSignExtend(instr instruction, pc *uint64, env Environment, contract *Cont
}
}
func
opNot
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opNot
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
:=
stack
.
pop
()
stack
.
push
(
U256
(
x
.
Not
(
x
)))
}
func
opLt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opLt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
if
x
.
Cmp
(
y
)
<
0
{
stack
.
push
(
big
.
NewInt
(
1
))
...
...
@@ -227,7 +227,7 @@ func opLt(instr instruction, pc *uint64, env Environment, contract *Contract, me
}
}
func
opGt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opGt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
if
x
.
Cmp
(
y
)
>
0
{
stack
.
push
(
big
.
NewInt
(
1
))
...
...
@@ -236,7 +236,7 @@ func opGt(instr instruction, pc *uint64, env Environment, contract *Contract, me
}
}
func
opSlt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSlt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
pop
())
if
x
.
Cmp
(
S256
(
y
))
<
0
{
stack
.
push
(
big
.
NewInt
(
1
))
...
...
@@ -245,7 +245,7 @@ func opSlt(instr instruction, pc *uint64, env Environment, contract *Contract, m
}
}
func
opSgt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSgt
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
pop
())
if
x
.
Cmp
(
y
)
>
0
{
stack
.
push
(
big
.
NewInt
(
1
))
...
...
@@ -254,7 +254,7 @@ func opSgt(instr instruction, pc *uint64, env Environment, contract *Contract, m
}
}
func
opEq
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opEq
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
if
x
.
Cmp
(
y
)
==
0
{
stack
.
push
(
big
.
NewInt
(
1
))
...
...
@@ -263,7 +263,7 @@ func opEq(instr instruction, pc *uint64, env Environment, contract *Contract, me
}
}
func
opIszero
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opIszero
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
:=
stack
.
pop
()
if
x
.
Cmp
(
common
.
Big0
)
>
0
{
stack
.
push
(
new
(
big
.
Int
))
...
...
@@ -272,19 +272,19 @@ func opIszero(instr instruction, pc *uint64, env Environment, contract *Contract
}
}
func
opAnd
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opAnd
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
x
.
And
(
x
,
y
))
}
func
opOr
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opOr
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
x
.
Or
(
x
,
y
))
}
func
opXor
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opXor
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
stack
.
push
(
x
.
Xor
(
x
,
y
))
}
func
opByte
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opByte
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
th
,
val
:=
stack
.
pop
(),
stack
.
pop
()
if
th
.
Cmp
(
big
.
NewInt
(
32
))
<
0
{
byte
:=
big
.
NewInt
(
int64
(
common
.
LeftPadBytes
(
val
.
Bytes
(),
32
)[
th
.
Int64
()]))
...
...
@@ -293,7 +293,7 @@ func opByte(instr instruction, pc *uint64, env Environment, contract *Contract,
stack
.
push
(
new
(
big
.
Int
))
}
}
func
opAddmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opAddmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
,
z
:=
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
()
if
z
.
Cmp
(
Zero
)
>
0
{
add
:=
x
.
Add
(
x
,
y
)
...
...
@@ -303,7 +303,7 @@ func opAddmod(instr instruction, pc *uint64, env Environment, contract *Contract
stack
.
push
(
new
(
big
.
Int
))
}
}
func
opMulmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMulmod
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
x
,
y
,
z
:=
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
()
if
z
.
Cmp
(
Zero
)
>
0
{
mul
:=
x
.
Mul
(
x
,
y
)
...
...
@@ -314,45 +314,45 @@ func opMulmod(instr instruction, pc *uint64, env Environment, contract *Contract
}
}
func
opSha3
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSha3
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
offset
,
size
:=
stack
.
pop
(),
stack
.
pop
()
hash
:=
crypto
.
Keccak256
(
memory
.
Get
(
offset
.
Int64
(),
size
.
Int64
()))
stack
.
push
(
common
.
BytesToBig
(
hash
))
}
func
opAddress
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opAddress
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
common
.
Bytes2Big
(
contract
.
Address
()
.
Bytes
()))
}
func
opBalance
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opBalance
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
addr
:=
common
.
BigToAddress
(
stack
.
pop
())
balance
:=
env
.
Db
()
.
GetBalance
(
addr
)
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
balance
))
}
func
opOrigin
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opOrigin
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
env
.
Origin
()
.
Big
())
}
func
opCaller
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCaller
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
contract
.
Caller
()
.
Big
())
}
func
opCallValue
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCallValue
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
contract
.
value
))
}
func
opCalldataLoad
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCalldataLoad
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
common
.
Bytes2Big
(
getData
(
contract
.
Input
,
stack
.
pop
(),
common
.
Big32
)))
}
func
opCalldataSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCalldataSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
big
.
NewInt
(
int64
(
len
(
contract
.
Input
))))
}
func
opCalldataCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCalldataCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
var
(
mOff
=
stack
.
pop
()
cOff
=
stack
.
pop
()
...
...
@@ -361,18 +361,18 @@ func opCalldataCopy(instr instruction, pc *uint64, env Environment, contract *Co
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
getData
(
contract
.
Input
,
cOff
,
l
))
}
func
opExtCodeSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opExtCodeSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
addr
:=
common
.
BigToAddress
(
stack
.
pop
())
l
:=
big
.
NewInt
(
int64
(
len
(
env
.
Db
()
.
GetCode
(
addr
))))
stack
.
push
(
l
)
}
func
opCodeSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCodeSize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
l
:=
big
.
NewInt
(
int64
(
len
(
contract
.
Code
)))
stack
.
push
(
l
)
}
func
opCodeCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCodeCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
var
(
mOff
=
stack
.
pop
()
cOff
=
stack
.
pop
()
...
...
@@ -383,7 +383,7 @@ func opCodeCopy(instr instruction, pc *uint64, env Environment, contract *Contra
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
codeCopy
)
}
func
opExtCodeCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opExtCodeCopy
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
var
(
addr
=
common
.
BigToAddress
(
stack
.
pop
())
mOff
=
stack
.
pop
()
...
...
@@ -395,11 +395,11 @@ func opExtCodeCopy(instr instruction, pc *uint64, env Environment, contract *Con
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
codeCopy
)
}
func
opGasprice
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opGasprice
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
contract
.
Price
))
}
func
opBlockhash
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opBlockhash
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
num
:=
stack
.
pop
()
n
:=
new
(
big
.
Int
)
.
Sub
(
env
.
BlockNumber
(),
common
.
Big257
)
...
...
@@ -410,43 +410,43 @@ func opBlockhash(instr instruction, pc *uint64, env Environment, contract *Contr
}
}
func
opCoinbase
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCoinbase
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
env
.
Coinbase
()
.
Big
())
}
func
opTimestamp
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opTimestamp
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
U256
(
new
(
big
.
Int
)
.
Set
(
env
.
Time
())))
}
func
opNumber
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opNumber
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
U256
(
new
(
big
.
Int
)
.
Set
(
env
.
BlockNumber
())))
}
func
opDifficulty
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opDifficulty
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
U256
(
new
(
big
.
Int
)
.
Set
(
env
.
Difficulty
())))
}
func
opGasLimit
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opGasLimit
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
U256
(
new
(
big
.
Int
)
.
Set
(
env
.
GasLimit
())))
}
func
opPop
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opPop
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
pop
()
}
func
opPush
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opPush
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
instr
.
data
))
}
func
opDup
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opDup
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
dup
(
int
(
instr
.
data
.
Int64
()))
}
func
opSwap
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSwap
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
swap
(
int
(
instr
.
data
.
Int64
()))
}
func
opLog
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opLog
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
n
:=
int
(
instr
.
data
.
Int64
())
topics
:=
make
([]
common
.
Hash
,
n
)
mStart
,
mSize
:=
stack
.
pop
(),
stack
.
pop
()
...
...
@@ -459,55 +459,55 @@ func opLog(instr instruction, pc *uint64, env Environment, contract *Contract, m
env
.
AddLog
(
log
)
}
func
opMload
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMload
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
offset
:=
stack
.
pop
()
val
:=
common
.
BigD
(
memory
.
Get
(
offset
.
Int64
(),
32
))
stack
.
push
(
val
)
}
func
opMstore
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMstore
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
// pop value of the stack
mStart
,
val
:=
stack
.
pop
(),
stack
.
pop
()
memory
.
Set
(
mStart
.
Uint64
(),
32
,
common
.
BigToBytes
(
val
,
256
))
}
func
opMstore8
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMstore8
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
off
,
val
:=
stack
.
pop
()
.
Int64
(),
stack
.
pop
()
.
Int64
()
memory
.
store
[
off
]
=
byte
(
val
&
0xff
)
}
func
opSload
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSload
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
loc
:=
common
.
BigToHash
(
stack
.
pop
())
val
:=
env
.
Db
()
.
GetState
(
contract
.
Address
(),
loc
)
.
Big
()
stack
.
push
(
val
)
}
func
opSstore
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSstore
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
loc
:=
common
.
BigToHash
(
stack
.
pop
())
val
:=
stack
.
pop
()
env
.
Db
()
.
SetState
(
contract
.
Address
(),
loc
,
common
.
BigToHash
(
val
))
}
func
opJump
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opJump
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
}
func
opJumpi
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opJumpi
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
}
func
opJumpdest
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opJumpdest
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
}
func
opPc
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opPc
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
instr
.
data
))
}
func
opMsize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opMsize
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
big
.
NewInt
(
int64
(
memory
.
Len
())))
}
func
opGas
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opGas
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
push
(
new
(
big
.
Int
)
.
Set
(
contract
.
Gas
))
}
func
opCreate
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCreate
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
var
(
value
=
stack
.
pop
()
offset
,
size
=
stack
.
pop
(),
stack
.
pop
()
...
...
@@ -529,7 +529,7 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
}
}
func
opCall
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCall
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
gas
:=
stack
.
pop
()
// pop gas and value of the stack.
addr
,
value
:=
stack
.
pop
(),
stack
.
pop
()
...
...
@@ -560,7 +560,7 @@ func opCall(instr instruction, pc *uint64, env Environment, contract *Contract,
}
}
func
opCallCode
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opCallCode
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
gas
:=
stack
.
pop
()
// pop gas and value of the stack.
addr
,
value
:=
stack
.
pop
(),
stack
.
pop
()
...
...
@@ -591,7 +591,7 @@ func opCallCode(instr instruction, pc *uint64, env Environment, contract *Contra
}
}
func
opDelegateCall
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opDelegateCall
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
gas
,
to
,
inOffset
,
inSize
,
outOffset
,
outSize
:=
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
(),
stack
.
pop
()
toAddr
:=
common
.
BigToAddress
(
to
)
...
...
@@ -605,12 +605,12 @@ func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Co
}
}
func
opReturn
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opReturn
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
}
func
opStop
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opStop
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
}
func
opSuicide
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
func
opSuicide
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
balance
:=
env
.
Db
()
.
GetBalance
(
contract
.
Address
())
env
.
Db
()
.
AddBalance
(
common
.
BigToAddress
(
stack
.
pop
()),
balance
)
...
...
@@ -621,7 +621,7 @@ func opSuicide(instr instruction, pc *uint64, env Environment, contract *Contrac
// make log instruction function
func
makeLog
(
size
int
)
instrFn
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
topics
:=
make
([]
common
.
Hash
,
size
)
mStart
,
mSize
:=
stack
.
pop
(),
stack
.
pop
()
for
i
:=
0
;
i
<
size
;
i
++
{
...
...
@@ -636,7 +636,7 @@ func makeLog(size int) instrFn {
// make push instruction function
func
makePush
(
size
uint64
,
bsize
*
big
.
Int
)
instrFn
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
byts
:=
getData
(
contract
.
Code
,
new
(
big
.
Int
)
.
SetUint64
(
*
pc
+
1
),
bsize
)
stack
.
push
(
common
.
Bytes2Big
(
byts
))
*
pc
+=
size
...
...
@@ -645,7 +645,7 @@ func makePush(size uint64, bsize *big.Int) instrFn {
// make push instruction function
func
makeDup
(
size
int64
)
instrFn
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
dup
(
int
(
size
))
}
}
...
...
@@ -654,7 +654,7 @@ func makeDup(size int64) instrFn {
func
makeSwap
(
size
int64
)
instrFn
{
// switch n + 1 otherwise n would be swapped with n
size
+=
1
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
{
return
func
(
instr
instruction
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
{
stack
.
swap
(
int
(
size
))
}
}
core/vm/jit.go
View file @
f81cff53
...
...
@@ -303,7 +303,7 @@ func RunProgram(program *Program, env Environment, contract *Contract, input []b
return
runProgram
(
program
,
0
,
NewMemory
(),
newstack
(),
env
,
contract
,
input
)
}
func
runProgram
(
program
*
Program
,
pcstart
uint64
,
mem
*
Memory
,
stack
*
s
tack
,
env
Environment
,
contract
*
Contract
,
input
[]
byte
)
([]
byte
,
error
)
{
func
runProgram
(
program
*
Program
,
pcstart
uint64
,
mem
*
Memory
,
stack
*
S
tack
,
env
Environment
,
contract
*
Contract
,
input
[]
byte
)
([]
byte
,
error
)
{
contract
.
Input
=
input
var
(
...
...
@@ -357,7 +357,7 @@ func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
// jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
// the operation. This does not reduce gas or resizes the memory.
func
jitCalculateGasAndSize
(
env
Environment
,
contract
*
Contract
,
instr
instruction
,
statedb
Database
,
mem
*
Memory
,
stack
*
s
tack
)
(
*
big
.
Int
,
*
big
.
Int
,
error
)
{
func
jitCalculateGasAndSize
(
env
Environment
,
contract
*
Contract
,
instr
instruction
,
statedb
Database
,
mem
*
Memory
,
stack
*
S
tack
)
(
*
big
.
Int
,
*
big
.
Int
,
error
)
{
var
(
gas
=
new
(
big
.
Int
)
newMemSize
*
big
.
Int
=
new
(
big
.
Int
)
...
...
@@ -491,7 +491,7 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
// jitBaseCheck is the same as baseCheck except it doesn't do the look up in the
// gas table. This is done during compilation instead.
func
jitBaseCheck
(
instr
instruction
,
stack
*
s
tack
,
gas
*
big
.
Int
)
error
{
func
jitBaseCheck
(
instr
instruction
,
stack
*
S
tack
,
gas
*
big
.
Int
)
error
{
err
:=
stack
.
require
(
instr
.
spop
)
if
err
!=
nil
{
return
err
...
...
core/vm/jit_test.go
View file @
f81cff53
...
...
@@ -179,11 +179,6 @@ func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
func
(
self
*
Env
)
Vm
()
Vm
{
return
self
.
evm
}
func
(
self
*
Env
)
Origin
()
common
.
Address
{
return
common
.
Address
{}
}
func
(
self
*
Env
)
BlockNumber
()
*
big
.
Int
{
return
big
.
NewInt
(
0
)
}
func
(
self
*
Env
)
AddStructLog
(
log
StructLog
)
{
}
func
(
self
*
Env
)
StructLogs
()
[]
StructLog
{
return
nil
}
//func (self *Env) PrevHash() []byte { return self.parent }
func
(
self
*
Env
)
Coinbase
()
common
.
Address
{
return
common
.
Address
{}
}
...
...
core/vm/logger.go
View file @
f81cff53
...
...
@@ -36,19 +36,12 @@ func (self Storage) Copy() Storage {
return
cpy
}
// StructLogCollector is the basic interface to capture emited logs by the EVM logger.
type
StructLogCollector
interface
{
// Adds the structured log to the collector.
AddStructLog
(
StructLog
)
}
// LogConfig are the configuration options for structured logger the EVM
type
LogConfig
struct
{
DisableMemory
bool
// disable memory capture
DisableStack
bool
// disable stack capture
DisableStorage
bool
// disable storage capture
FullStorage
bool
// show full storage (slow)
Collector
StructLogCollector
// the log collector
}
// StructLog is emitted to the Environment each cycle and lists information about the current internal state
...
...
@@ -65,36 +58,42 @@ type StructLog struct {
Err
error
}
// Logger is an EVM state logger and implements VmLogger.
// Tracer is used to collect execution traces from an EVM transaction
// execution. CaptureState is called for each step of the VM with the
// current VM state.
// Note that reference types are actual VM data structures; make copies
// if you need to retain them beyond the current call.
type
Tracer
interface
{
CaptureState
(
env
Environment
,
pc
uint64
,
op
OpCode
,
gas
,
cost
*
big
.
Int
,
memory
*
Memory
,
stack
*
Stack
,
contract
*
Contract
,
depth
int
,
err
error
)
}
// StructLogger is an EVM state logger and implements Tracer.
//
// Logger can capture state based on the given Log configuration and also keeps
//
Struct
Logger can capture state based on the given Log configuration and also keeps
// a track record of modified storage which is used in reporting snapshots of the
// contract their storage.
type
Logger
struct
{
type
Struct
Logger
struct
{
cfg
LogConfig
env
Environment
logs
[]
StructLog
changedValues
map
[
common
.
Address
]
Storage
}
// newLogger returns a new logger
func
newLogger
(
cfg
LogConfig
,
env
Environment
)
*
Logger
{
return
&
Logger
{
cfg
:
cfg
,
env
:
env
,
// NewLogger returns a new logger
func
NewStructLogger
(
cfg
*
LogConfig
)
*
StructLogger
{
logger
:=
&
StructLogger
{
changedValues
:
make
(
map
[
common
.
Address
]
Storage
),
}
if
cfg
!=
nil
{
logger
.
cfg
=
*
cfg
}
return
logger
}
// captureState logs a new structured log message and pushes it out to the environment
//
// captureState also tracks SSTORE ops to track dirty values.
func
(
l
*
Logger
)
captureState
(
pc
uint64
,
op
OpCode
,
gas
,
cost
*
big
.
Int
,
memory
*
Memory
,
stack
*
stack
,
contract
*
Contract
,
depth
int
,
err
error
)
{
// short circuit if no log collector is present
if
l
.
cfg
.
Collector
==
nil
{
return
}
func
(
l
*
StructLogger
)
CaptureState
(
env
Environment
,
pc
uint64
,
op
OpCode
,
gas
,
cost
*
big
.
Int
,
memory
*
Memory
,
stack
*
Stack
,
contract
*
Contract
,
depth
int
,
err
error
)
{
// initialise new changed values storage container for this contract
// if not present.
if
l
.
changedValues
[
contract
.
Address
()]
==
nil
{
...
...
@@ -139,7 +138,7 @@ func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *
storage
=
make
(
Storage
)
// Get the contract account and loop over each storage entry. This may involve looping over
// the trie and is a very expensive process.
l
.
env
.
Db
()
.
GetAccount
(
contract
.
Address
())
.
ForEachStorage
(
func
(
key
,
value
common
.
Hash
)
bool
{
env
.
Db
()
.
GetAccount
(
contract
.
Address
())
.
ForEachStorage
(
func
(
key
,
value
common
.
Hash
)
bool
{
storage
[
key
]
=
value
// Return true, indicating we'd like to continue.
return
true
...
...
@@ -150,9 +149,14 @@ func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *
}
}
// create a new snaptshot of the EVM.
log
:=
StructLog
{
pc
,
op
,
new
(
big
.
Int
)
.
Set
(
gas
),
cost
,
mem
,
stck
,
storage
,
l
.
env
.
Depth
(),
err
}
// Add the log to the collector
l
.
cfg
.
Collector
.
AddStructLog
(
log
)
log
:=
StructLog
{
pc
,
op
,
new
(
big
.
Int
)
.
Set
(
gas
),
cost
,
mem
,
stck
,
storage
,
env
.
Depth
(),
err
}
l
.
logs
=
append
(
l
.
logs
,
log
)
}
// StructLogs returns a list of captured log entries
func
(
l
*
StructLogger
)
StructLogs
()
[]
StructLog
{
return
l
.
logs
}
// StdErrFormat formats a slice of StructLogs to human readable format
...
...
core/vm/logger_test.go
View file @
f81cff53
...
...
@@ -54,12 +54,11 @@ func newDummyEnv(ref *dummyContractRef) *dummyEnv {
func
(
d
dummyEnv
)
GetAccount
(
common
.
Address
)
Account
{
return
d
.
ref
}
func
(
d
dummyEnv
)
AddStructLog
(
StructLog
)
{}
func
TestStoreCapture
(
t
*
testing
.
T
)
{
var
(
env
=
NewEnv
(
true
,
false
)
logger
=
newLogger
(
LogConfig
{
Collector
:
env
},
env
)
logger
=
NewStructLogger
(
nil
)
mem
=
NewMemory
()
stack
=
newstack
()
contract
=
NewContract
(
&
dummyContractRef
{},
&
dummyContractRef
{},
new
(
big
.
Int
),
new
(
big
.
Int
),
new
(
big
.
Int
))
...
...
@@ -69,7 +68,7 @@ func TestStoreCapture(t *testing.T) {
var
index
common
.
Hash
logger
.
captureState
(
0
,
SSTORE
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
logger
.
CaptureState
(
env
,
0
,
SSTORE
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
if
len
(
logger
.
changedValues
[
contract
.
Address
()])
==
0
{
t
.
Fatalf
(
"expected exactly 1 changed value on address %x, got %d"
,
contract
.
Address
(),
len
(
logger
.
changedValues
[
contract
.
Address
()]))
}
...
...
@@ -86,18 +85,18 @@ func TestStorageCapture(t *testing.T) {
ref
=
&
dummyContractRef
{}
contract
=
NewContract
(
ref
,
ref
,
new
(
big
.
Int
),
new
(
big
.
Int
),
new
(
big
.
Int
))
env
=
newDummyEnv
(
ref
)
logger
=
newLogger
(
LogConfig
{
Collector
:
env
},
env
)
logger
=
NewStructLogger
(
nil
)
mem
=
NewMemory
()
stack
=
newstack
()
)
logger
.
captureState
(
0
,
STOP
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
logger
.
CaptureState
(
env
,
0
,
STOP
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
if
ref
.
calledForEach
{
t
.
Error
(
"didn't expect for each to be called"
)
}
logger
=
newLogger
(
LogConfig
{
Collector
:
env
,
FullStorage
:
true
},
env
)
logger
.
captureState
(
0
,
STOP
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
logger
=
NewStructLogger
(
&
LogConfig
{
FullStorage
:
true
}
)
logger
.
CaptureState
(
env
,
0
,
STOP
,
new
(
big
.
Int
),
new
(
big
.
Int
),
mem
,
stack
,
contract
,
0
,
nil
)
if
!
ref
.
calledForEach
{
t
.
Error
(
"expected for each to be called"
)
}
...
...
core/vm/runtime/env.go
View file @
f81cff53
...
...
@@ -39,8 +39,6 @@ type Env struct {
difficulty
*
big
.
Int
gasLimit
*
big
.
Int
logs
[]
vm
.
StructLog
getHashFn
func
(
uint64
)
common
.
Hash
evm
*
vm
.
EVM
...
...
@@ -62,23 +60,11 @@ func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
Debug
:
cfg
.
Debug
,
EnableJit
:
!
cfg
.
DisableJit
,
ForceJit
:
!
cfg
.
DisableJit
,
Logger
:
vm
.
LogConfig
{
Collector
:
env
,
},
})
return
env
}
func
(
self
*
Env
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
Env
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
func
(
self
*
Env
)
RuleSet
()
vm
.
RuleSet
{
return
self
.
ruleSet
}
func
(
self
*
Env
)
Vm
()
vm
.
Vm
{
return
self
.
evm
}
func
(
self
*
Env
)
Origin
()
common
.
Address
{
return
self
.
origin
}
...
...
core/vm/segments.go
View file @
f81cff53
...
...
@@ -24,7 +24,7 @@ type jumpSeg struct {
gas
*
big
.
Int
}
func
(
j
jumpSeg
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
([]
byte
,
error
)
{
func
(
j
jumpSeg
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
([]
byte
,
error
)
{
if
!
contract
.
UseGas
(
j
.
gas
)
{
return
nil
,
OutOfGasError
}
...
...
@@ -42,7 +42,7 @@ type pushSeg struct {
gas
*
big
.
Int
}
func
(
s
pushSeg
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
s
tack
)
([]
byte
,
error
)
{
func
(
s
pushSeg
)
do
(
program
*
Program
,
pc
*
uint64
,
env
Environment
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
S
tack
)
([]
byte
,
error
)
{
// Use the calculated gas. When insufficient gas is present, use all gas and return an
// Out Of Gas error
if
!
contract
.
UseGas
(
s
.
gas
)
{
...
...
core/vm/stack.go
View file @
f81cff53
...
...
@@ -24,58 +24,58 @@ import (
// stack is an object for basic stack operations. Items popped to the stack are
// expected to be changed and modified. stack does not take care of adding newly
// initialised objects.
type
s
tack
struct
{
type
S
tack
struct
{
data
[]
*
big
.
Int
}
func
newstack
()
*
s
tack
{
return
&
s
tack
{}
func
newstack
()
*
S
tack
{
return
&
S
tack
{}
}
func
(
st
*
s
tack
)
Data
()
[]
*
big
.
Int
{
func
(
st
*
S
tack
)
Data
()
[]
*
big
.
Int
{
return
st
.
data
}
func
(
st
*
s
tack
)
push
(
d
*
big
.
Int
)
{
func
(
st
*
S
tack
)
push
(
d
*
big
.
Int
)
{
// NOTE push limit (1024) is checked in baseCheck
//stackItem := new(big.Int).Set(d)
//st.data = append(st.data, stackItem)
st
.
data
=
append
(
st
.
data
,
d
)
}
func
(
st
*
s
tack
)
pushN
(
ds
...*
big
.
Int
)
{
func
(
st
*
S
tack
)
pushN
(
ds
...*
big
.
Int
)
{
st
.
data
=
append
(
st
.
data
,
ds
...
)
}
func
(
st
*
s
tack
)
pop
()
(
ret
*
big
.
Int
)
{
func
(
st
*
S
tack
)
pop
()
(
ret
*
big
.
Int
)
{
ret
=
st
.
data
[
len
(
st
.
data
)
-
1
]
st
.
data
=
st
.
data
[
:
len
(
st
.
data
)
-
1
]
return
}
func
(
st
*
s
tack
)
len
()
int
{
func
(
st
*
S
tack
)
len
()
int
{
return
len
(
st
.
data
)
}
func
(
st
*
s
tack
)
swap
(
n
int
)
{
func
(
st
*
S
tack
)
swap
(
n
int
)
{
st
.
data
[
st
.
len
()
-
n
],
st
.
data
[
st
.
len
()
-
1
]
=
st
.
data
[
st
.
len
()
-
1
],
st
.
data
[
st
.
len
()
-
n
]
}
func
(
st
*
s
tack
)
dup
(
n
int
)
{
func
(
st
*
S
tack
)
dup
(
n
int
)
{
st
.
push
(
new
(
big
.
Int
)
.
Set
(
st
.
data
[
st
.
len
()
-
n
]))
}
func
(
st
*
s
tack
)
peek
()
*
big
.
Int
{
func
(
st
*
S
tack
)
peek
()
*
big
.
Int
{
return
st
.
data
[
st
.
len
()
-
1
]
}
func
(
st
*
s
tack
)
require
(
n
int
)
error
{
func
(
st
*
S
tack
)
require
(
n
int
)
error
{
if
st
.
len
()
<
n
{
return
fmt
.
Errorf
(
"stack underflow (%d <=> %d)"
,
len
(
st
.
data
),
n
)
}
return
nil
}
func
(
st
*
s
tack
)
Print
()
{
func
(
st
*
S
tack
)
Print
()
{
fmt
.
Println
(
"### stack ###"
)
if
len
(
st
.
data
)
>
0
{
for
i
,
val
:=
range
st
.
data
{
...
...
core/vm/vm.go
View file @
f81cff53
...
...
@@ -33,7 +33,7 @@ type Config struct {
Debug
bool
EnableJit
bool
ForceJit
bool
Logger
LogConfig
Tracer
Tracer
}
// EVM is used to run Ethereum based contracts and will utilise the
...
...
@@ -44,22 +44,14 @@ type EVM struct {
env
Environment
jumpTable
vmJumpTable
cfg
Config
logger
*
Logger
}
// New returns a new instance of the EVM.
func
New
(
env
Environment
,
cfg
Config
)
*
EVM
{
var
logger
*
Logger
if
cfg
.
Debug
{
logger
=
newLogger
(
cfg
.
Logger
,
env
)
}
return
&
EVM
{
env
:
env
,
jumpTable
:
newJumpTable
(
env
.
RuleSet
(),
env
.
BlockNumber
()),
cfg
:
cfg
,
logger
:
logger
,
}
}
...
...
@@ -149,7 +141,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
defer
func
()
{
if
err
!=
nil
&&
evm
.
cfg
.
Debug
{
evm
.
logger
.
captureState
(
pc
,
op
,
contract
.
Gas
,
cost
,
mem
,
stack
,
contract
,
evm
.
env
.
Depth
(),
err
)
evm
.
cfg
.
Tracer
.
CaptureState
(
evm
.
env
,
pc
,
op
,
contract
.
Gas
,
cost
,
mem
,
stack
,
contract
,
evm
.
env
.
Depth
(),
err
)
}
}()
...
...
@@ -191,7 +183,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
mem
.
Resize
(
newMemSize
.
Uint64
())
// Add a log message
if
evm
.
cfg
.
Debug
{
evm
.
logger
.
captureState
(
pc
,
op
,
contract
.
Gas
,
cost
,
mem
,
stack
,
contract
,
evm
.
env
.
Depth
(),
nil
)
evm
.
cfg
.
Tracer
.
CaptureState
(
evm
.
env
,
pc
,
op
,
contract
.
Gas
,
cost
,
mem
,
stack
,
contract
,
evm
.
env
.
Depth
(),
nil
)
}
if
opPtr
:=
evm
.
jumpTable
[
op
];
opPtr
.
valid
{
...
...
@@ -241,7 +233,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
// calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
// the operation. This does not reduce gas or resizes the memory.
func
calculateGasAndSize
(
env
Environment
,
contract
*
Contract
,
caller
ContractRef
,
op
OpCode
,
statedb
Database
,
mem
*
Memory
,
stack
*
s
tack
)
(
*
big
.
Int
,
*
big
.
Int
,
error
)
{
func
calculateGasAndSize
(
env
Environment
,
contract
*
Contract
,
caller
ContractRef
,
op
OpCode
,
statedb
Database
,
mem
*
Memory
,
stack
*
S
tack
)
(
*
big
.
Int
,
*
big
.
Int
,
error
)
{
var
(
gas
=
new
(
big
.
Int
)
newMemSize
*
big
.
Int
=
new
(
big
.
Int
)
...
...
core/vm_env.go
View file @
f81cff53
...
...
@@ -49,7 +49,6 @@ type VMEnv struct {
header
*
types
.
Header
// Header information
chain
*
BlockChain
// Blockchain handle
logs
[]
vm
.
StructLog
// Logs for the custom structured logger
getHashFn
func
(
uint64
)
common
.
Hash
// getHashFn callback is used to retrieve block hashes
}
...
...
@@ -63,11 +62,6 @@ func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, m
getHashFn
:
GetHashFn
(
header
.
ParentHash
,
chain
),
}
// if no log collector is present set self as the collector
if
cfg
.
Logger
.
Collector
==
nil
{
cfg
.
Logger
.
Collector
=
env
}
env
.
evm
=
vm
.
New
(
env
,
cfg
)
return
env
}
...
...
@@ -121,11 +115,3 @@ func (self *VMEnv) DelegateCall(me vm.ContractRef, addr common.Address, data []b
func
(
self
*
VMEnv
)
Create
(
me
vm
.
ContractRef
,
data
[]
byte
,
gas
,
price
,
value
*
big
.
Int
)
([]
byte
,
common
.
Address
,
error
)
{
return
Create
(
self
,
me
,
data
,
gas
,
price
,
value
)
}
func
(
self
*
VMEnv
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
VMEnv
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
eth/api.go
View file @
f81cff53
...
...
@@ -319,7 +319,7 @@ type BlockTraceResult struct {
// TraceBlock processes the given block's RLP but does not import the block in to
// the chain.
func
(
api
*
PrivateDebugAPI
)
TraceBlock
(
blockRlp
[]
byte
,
config
*
vm
.
Config
)
BlockTraceResult
{
func
(
api
*
PrivateDebugAPI
)
TraceBlock
(
blockRlp
[]
byte
,
config
*
vm
.
Log
Config
)
BlockTraceResult
{
var
block
types
.
Block
err
:=
rlp
.
Decode
(
bytes
.
NewReader
(
blockRlp
),
&
block
)
if
err
!=
nil
{
...
...
@@ -336,7 +336,7 @@ func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.Config) Block
// TraceBlockFromFile loads the block's RLP from the given file name and attempts to
// process it but does not import the block in to the chain.
func
(
api
*
PrivateDebugAPI
)
TraceBlockFromFile
(
file
string
,
config
*
vm
.
Config
)
BlockTraceResult
{
func
(
api
*
PrivateDebugAPI
)
TraceBlockFromFile
(
file
string
,
config
*
vm
.
Log
Config
)
BlockTraceResult
{
blockRlp
,
err
:=
ioutil
.
ReadFile
(
file
)
if
err
!=
nil
{
return
BlockTraceResult
{
Error
:
fmt
.
Sprintf
(
"could not read file: %v"
,
err
)}
...
...
@@ -345,7 +345,7 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(file string, config *vm.Config) B
}
// TraceBlockByNumber processes the block by canonical block number.
func
(
api
*
PrivateDebugAPI
)
TraceBlockByNumber
(
number
uint64
,
config
*
vm
.
Config
)
BlockTraceResult
{
func
(
api
*
PrivateDebugAPI
)
TraceBlockByNumber
(
number
uint64
,
config
*
vm
.
Log
Config
)
BlockTraceResult
{
// Fetch the block that we aim to reprocess
block
:=
api
.
eth
.
BlockChain
()
.
GetBlockByNumber
(
number
)
if
block
==
nil
{
...
...
@@ -361,7 +361,7 @@ func (api *PrivateDebugAPI) TraceBlockByNumber(number uint64, config *vm.Config)
}
// TraceBlockByHash processes the block by hash.
func
(
api
*
PrivateDebugAPI
)
TraceBlockByHash
(
hash
common
.
Hash
,
config
*
vm
.
Config
)
BlockTraceResult
{
func
(
api
*
PrivateDebugAPI
)
TraceBlockByHash
(
hash
common
.
Hash
,
config
*
vm
.
Log
Config
)
BlockTraceResult
{
// Fetch the block that we aim to reprocess
block
:=
api
.
eth
.
BlockChain
()
.
GetBlockByHash
(
hash
)
if
block
==
nil
{
...
...
@@ -376,49 +376,38 @@ func (api *PrivateDebugAPI) TraceBlockByHash(hash common.Hash, config *vm.Config
}
}
// TraceCollector collects EVM structered logs.
//
// TraceCollector implements vm.Collector
type
TraceCollector
struct
{
traces
[]
vm
.
StructLog
}
// AddStructLog adds a structered log.
func
(
t
*
TraceCollector
)
AddStructLog
(
slog
vm
.
StructLog
)
{
t
.
traces
=
append
(
t
.
traces
,
slog
)
}
// traceBlock processes the given block but does not save the state.
func
(
api
*
PrivateDebugAPI
)
traceBlock
(
block
*
types
.
Block
,
config
*
vm
.
Config
)
(
bool
,
[]
vm
.
StructLog
,
error
)
{
func
(
api
*
PrivateDebugAPI
)
traceBlock
(
block
*
types
.
Block
,
logConfig
*
vm
.
Log
Config
)
(
bool
,
[]
vm
.
StructLog
,
error
)
{
// Validate and reprocess the block
var
(
blockchain
=
api
.
eth
.
BlockChain
()
validator
=
blockchain
.
Validator
()
processor
=
blockchain
.
Processor
()
collector
=
&
TraceCollector
{}
)
if
config
==
nil
{
config
=
new
(
vm
.
Config
)
structLogger
:=
vm
.
NewStructLogger
(
logConfig
)
config
:=
vm
.
Config
{
Debug
:
true
,
Tracer
:
structLogger
,
}
config
.
Debug
=
true
// make sure debug is set.
config
.
Logger
.
Collector
=
collector
if
err
:=
core
.
ValidateHeader
(
api
.
config
,
blockchain
.
AuxValidator
(),
block
.
Header
(),
blockchain
.
GetHeader
(
block
.
ParentHash
(),
block
.
NumberU64
()
-
1
),
true
,
false
);
err
!=
nil
{
return
false
,
collector
.
traces
,
err
return
false
,
structLogger
.
StructLogs
()
,
err
}
statedb
,
err
:=
state
.
New
(
blockchain
.
GetBlock
(
block
.
ParentHash
(),
block
.
NumberU64
()
-
1
)
.
Root
(),
api
.
eth
.
ChainDb
())
if
err
!=
nil
{
return
false
,
collector
.
traces
,
err
return
false
,
structLogger
.
StructLogs
()
,
err
}
receipts
,
_
,
usedGas
,
err
:=
processor
.
Process
(
block
,
statedb
,
*
config
)
receipts
,
_
,
usedGas
,
err
:=
processor
.
Process
(
block
,
statedb
,
config
)
if
err
!=
nil
{
return
false
,
collector
.
traces
,
err
return
false
,
structLogger
.
StructLogs
()
,
err
}
if
err
:=
validator
.
ValidateState
(
block
,
blockchain
.
GetBlock
(
block
.
ParentHash
(),
block
.
NumberU64
()
-
1
),
statedb
,
receipts
,
usedGas
);
err
!=
nil
{
return
false
,
collector
.
traces
,
err
return
false
,
structLogger
.
StructLogs
()
,
err
}
return
true
,
collector
.
traces
,
nil
return
true
,
structLogger
.
StructLogs
()
,
nil
}
// callmsg is the message type used for call transations.
...
...
@@ -452,10 +441,9 @@ func formatError(err error) string {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
func
(
api
*
PrivateDebugAPI
)
TraceTransaction
(
txHash
common
.
Hash
,
logger
*
vm
.
LogConfig
)
(
*
ethapi
.
ExecutionResult
,
error
)
{
if
logger
==
nil
{
logger
=
new
(
vm
.
LogConfig
)
}
func
(
api
*
PrivateDebugAPI
)
TraceTransaction
(
txHash
common
.
Hash
,
logConfig
*
vm
.
LogConfig
)
(
*
ethapi
.
ExecutionResult
,
error
)
{
logger
:=
vm
.
NewStructLogger
(
logConfig
)
// Retrieve the tx from the chain and the containing block
tx
,
blockHash
,
_
,
txIndex
:=
core
.
GetTransaction
(
api
.
eth
.
ChainDb
(),
txHash
)
if
tx
==
nil
{
...
...
@@ -500,7 +488,7 @@ func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogC
continue
}
// Otherwise trace the transaction and return
vmenv
:=
core
.
NewEnv
(
stateDb
,
api
.
config
,
api
.
eth
.
BlockChain
(),
msg
,
block
.
Header
(),
vm
.
Config
{
Debug
:
true
,
Logger
:
*
logger
})
vmenv
:=
core
.
NewEnv
(
stateDb
,
api
.
config
,
api
.
eth
.
BlockChain
(),
msg
,
block
.
Header
(),
vm
.
Config
{
Debug
:
true
,
Tracer
:
logger
})
ret
,
gas
,
err
:=
core
.
ApplyMessage
(
vmenv
,
msg
,
new
(
core
.
GasPool
)
.
AddGas
(
tx
.
Gas
()))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"tracing failed: %v"
,
err
)
...
...
@@ -508,7 +496,7 @@ func (api *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger *vm.LogC
return
&
ethapi
.
ExecutionResult
{
Gas
:
gas
,
ReturnValue
:
fmt
.
Sprintf
(
"%x"
,
ret
),
StructLogs
:
ethapi
.
FormatLogs
(
vmenv
.
StructLogs
()),
StructLogs
:
ethapi
.
FormatLogs
(
logger
.
StructLogs
()),
},
nil
}
return
nil
,
errors
.
New
(
"database inconsistency"
)
...
...
internal/ethapi/api.go
View file @
f81cff53
...
...
@@ -584,60 +584,6 @@ func FormatLogs(structLogs []vm.StructLog) []StructLogRes {
return
formattedStructLogs
}
// TraceCall executes a call and returns the amount of gas, created logs and optionally returned values.
func
(
s
*
PublicBlockChainAPI
)
TraceCall
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
)
(
*
ExecutionResult
,
error
)
{
state
,
header
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
blockNr
)
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
}
var
addr
common
.
Address
if
args
.
From
==
(
common
.
Address
{})
{
accounts
:=
s
.
b
.
AccountManager
()
.
Accounts
()
if
len
(
accounts
)
==
0
{
addr
=
common
.
Address
{}
}
else
{
addr
=
accounts
[
0
]
.
Address
}
}
else
{
addr
=
args
.
From
}
// Assemble the CALL invocation
msg
:=
callmsg
{
addr
:
addr
,
to
:
args
.
To
,
gas
:
args
.
Gas
.
BigInt
(),
gasPrice
:
args
.
GasPrice
.
BigInt
(),
value
:
args
.
Value
.
BigInt
(),
data
:
common
.
FromHex
(
args
.
Data
),
}
if
msg
.
gas
.
Cmp
(
common
.
Big0
)
==
0
{
msg
.
gas
=
big
.
NewInt
(
50000000
)
}
if
msg
.
gasPrice
.
Cmp
(
common
.
Big0
)
==
0
{
msg
.
gasPrice
=
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
50
),
common
.
Shannon
)
}
// Execute the call and return
vmenv
,
vmError
,
err
:=
s
.
b
.
GetVMEnv
(
ctx
,
msg
,
state
,
header
)
if
err
!=
nil
{
return
nil
,
err
}
gp
:=
new
(
core
.
GasPool
)
.
AddGas
(
common
.
MaxBig
)
ret
,
gas
,
err
:=
core
.
ApplyMessage
(
vmenv
,
msg
,
gp
)
if
err
:=
vmError
();
err
!=
nil
{
return
nil
,
err
}
return
&
ExecutionResult
{
Gas
:
gas
,
ReturnValue
:
fmt
.
Sprintf
(
"%x"
,
ret
),
StructLogs
:
FormatLogs
(
vmenv
.
StructLogs
()),
},
nil
}
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
// transaction hashes.
...
...
tests/util.go
View file @
f81cff53
...
...
@@ -166,8 +166,6 @@ type Env struct {
difficulty
*
big
.
Int
gasLimit
*
big
.
Int
logs
[]
vm
.
StructLog
vmTest
bool
evm
*
vm
.
EVM
...
...
@@ -181,14 +179,6 @@ func NewEnv(ruleSet RuleSet, state *state.StateDB) *Env {
return
env
}
func
(
self
*
Env
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
Env
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
func
NewEnvFromMap
(
ruleSet
RuleSet
,
state
*
state
.
StateDB
,
envValues
map
[
string
]
string
,
exeValues
map
[
string
]
string
)
*
Env
{
env
:=
NewEnv
(
ruleSet
,
state
)
...
...
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