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
9007f2bb
Commit
9007f2bb
authored
Mar 09, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
reworked stack
parent
0795fd27
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
352 additions
and
442 deletions
+352
-442
gh_test.go
tests/vm/gh_test.go
+0
-6
debugger.go
vm/debugger.go
+0
-9
gas.go
vm/gas.go
+86
-0
memory.go
vm/memory.go
+72
-0
stack.go
vm/stack.go
+28
-142
vm.go
vm/vm.go
+166
-285
No files found.
tests/vm/gh_test.go
View file @
9007f2bb
...
...
@@ -11,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/tests/helper"
"github.com/ethereum/go-ethereum/vm"
)
type
Account
struct
{
...
...
@@ -81,11 +80,6 @@ func RunVmTest(p string, t *testing.T) {
helper
.
CreateFileTests
(
t
,
p
,
&
tests
)
for
name
,
test
:=
range
tests
{
vm
.
Debug
=
true
helper
.
Logger
.
SetLogLevel
(
4
)
if
name
!=
"addmod0"
{
continue
}
db
,
_
:=
ethdb
.
NewMemDatabase
()
statedb
:=
state
.
New
(
nil
,
db
)
for
addr
,
account
:=
range
test
.
Pre
{
...
...
vm/debugger.go
View file @
9007f2bb
package
vm
import
"github.com/ethereum/go-ethereum/state"
type
Debugger
interface
{
BreakHook
(
step
int
,
op
OpCode
,
mem
*
Memory
,
stack
*
Stack
,
object
*
state
.
StateObject
)
bool
StepHook
(
step
int
,
op
OpCode
,
mem
*
Memory
,
stack
*
Stack
,
object
*
state
.
StateObject
)
bool
BreakPoints
()
[]
int64
SetCode
(
byteCode
[]
byte
)
}
vm/gas.go
0 → 100644
View file @
9007f2bb
package
vm
import
"math/big"
type
req
struct
{
stack
int
gas
*
big
.
Int
}
var
_baseCheck
=
map
[
OpCode
]
req
{
// Req stack Gas price
ADD
:
{
2
,
GasFastestStep
},
LT
:
{
2
,
GasFastestStep
},
GT
:
{
2
,
GasFastestStep
},
SLT
:
{
2
,
GasFastestStep
},
SGT
:
{
2
,
GasFastestStep
},
EQ
:
{
2
,
GasFastestStep
},
ISZERO
:
{
1
,
GasFastestStep
},
SUB
:
{
2
,
GasFastestStep
},
AND
:
{
2
,
GasFastestStep
},
OR
:
{
2
,
GasFastestStep
},
XOR
:
{
2
,
GasFastestStep
},
NOT
:
{
1
,
GasFastestStep
},
BYTE
:
{
2
,
GasFastestStep
},
CALLDATALOAD
:
{
1
,
GasFastestStep
},
CALLDATACOPY
:
{
3
,
GasFastestStep
},
MLOAD
:
{
1
,
GasFastestStep
},
MSTORE
:
{
2
,
GasFastestStep
},
MSTORE8
:
{
2
,
GasFastestStep
},
CODECOPY
:
{
3
,
GasFastestStep
},
MUL
:
{
2
,
GasFastStep
},
DIV
:
{
2
,
GasFastStep
},
SDIV
:
{
2
,
GasFastStep
},
MOD
:
{
2
,
GasFastStep
},
SMOD
:
{
2
,
GasFastStep
},
SIGNEXTEND
:
{
2
,
GasFastStep
},
ADDMOD
:
{
3
,
GasMidStep
},
MULMOD
:
{
3
,
GasMidStep
},
JUMP
:
{
1
,
GasMidStep
},
JUMPI
:
{
2
,
GasSlowStep
},
EXP
:
{
2
,
GasSlowStep
},
ADDRESS
:
{
0
,
GasQuickStep
},
ORIGIN
:
{
0
,
GasQuickStep
},
CALLER
:
{
0
,
GasQuickStep
},
CALLVALUE
:
{
0
,
GasQuickStep
},
CODESIZE
:
{
0
,
GasQuickStep
},
GASPRICE
:
{
0
,
GasQuickStep
},
COINBASE
:
{
0
,
GasQuickStep
},
TIMESTAMP
:
{
0
,
GasQuickStep
},
NUMBER
:
{
0
,
GasQuickStep
},
CALLDATASIZE
:
{
0
,
GasQuickStep
},
DIFFICULTY
:
{
0
,
GasQuickStep
},
GASLIMIT
:
{
0
,
GasQuickStep
},
POP
:
{
0
,
GasQuickStep
},
PC
:
{
0
,
GasQuickStep
},
MSIZE
:
{
0
,
GasQuickStep
},
GAS
:
{
0
,
GasQuickStep
},
BLOCKHASH
:
{
1
,
GasExtStep
},
BALANCE
:
{
0
,
GasExtStep
},
EXTCODESIZE
:
{
1
,
GasExtStep
},
EXTCODECOPY
:
{
4
,
GasExtStep
},
SLOAD
:
{
1
,
GasStorageGet
},
SSTORE
:
{
2
,
Zero
},
SHA3
:
{
1
,
GasSha3Base
},
CREATE
:
{
3
,
GasCreate
},
CALL
:
{
7
,
GasCall
},
CALLCODE
:
{
7
,
GasCall
},
JUMPDEST
:
{
0
,
GasJumpDest
},
SUICIDE
:
{
1
,
Zero
},
RETURN
:
{
2
,
Zero
},
}
func
baseCheck
(
op
OpCode
,
stack
*
stack
,
gas
*
big
.
Int
)
{
if
r
,
ok
:=
_baseCheck
[
op
];
ok
{
stack
.
require
(
r
.
stack
)
gas
.
Add
(
gas
,
r
.
gas
)
}
}
func
toWordSize
(
size
*
big
.
Int
)
*
big
.
Int
{
tmp
:=
new
(
big
.
Int
)
tmp
.
Add
(
size
,
u256
(
31
))
tmp
.
Div
(
tmp
,
u256
(
32
))
return
tmp
}
vm/memory.go
0 → 100644
View file @
9007f2bb
package
vm
import
"fmt"
type
Memory
struct
{
store
[]
byte
}
func
NewMemory
()
*
Memory
{
return
&
Memory
{
nil
}
}
func
(
m
*
Memory
)
Set
(
offset
,
size
uint64
,
value
[]
byte
)
{
if
len
(
value
)
>
0
{
totSize
:=
offset
+
size
lenSize
:=
uint64
(
len
(
m
.
store
)
-
1
)
if
totSize
>
lenSize
{
// Calculate the diff between the sizes
diff
:=
totSize
-
lenSize
if
diff
>
0
{
// Create a new empty slice and append it
newSlice
:=
make
([]
byte
,
diff
-
1
)
// Resize slice
m
.
store
=
append
(
m
.
store
,
newSlice
...
)
}
}
copy
(
m
.
store
[
offset
:
offset
+
size
],
value
)
}
}
func
(
m
*
Memory
)
Resize
(
size
uint64
)
{
if
uint64
(
m
.
Len
())
<
size
{
m
.
store
=
append
(
m
.
store
,
make
([]
byte
,
size
-
uint64
(
m
.
Len
()))
...
)
}
}
func
(
self
*
Memory
)
Get
(
offset
,
size
int64
)
(
cpy
[]
byte
)
{
if
size
==
0
{
return
nil
}
if
len
(
self
.
store
)
>
int
(
offset
)
{
cpy
=
make
([]
byte
,
size
)
copy
(
cpy
,
self
.
store
[
offset
:
offset
+
size
])
return
}
return
}
func
(
m
*
Memory
)
Len
()
int
{
return
len
(
m
.
store
)
}
func
(
m
*
Memory
)
Data
()
[]
byte
{
return
m
.
store
}
func
(
m
*
Memory
)
Print
()
{
fmt
.
Printf
(
"### mem %d bytes ###
\n
"
,
len
(
m
.
store
))
if
len
(
m
.
store
)
>
0
{
addr
:=
0
for
i
:=
0
;
i
+
32
<=
len
(
m
.
store
);
i
+=
32
{
fmt
.
Printf
(
"%03d: % x
\n
"
,
addr
,
m
.
store
[
i
:
i
+
32
])
addr
++
}
}
else
{
fmt
.
Println
(
"-- empty --"
)
}
fmt
.
Println
(
"####################"
)
}
vm/stack.go
View file @
9007f2bb
...
...
@@ -5,98 +5,53 @@ import (
"math/big"
)
type
OpType
int
const
(
tNorm
=
iota
tData
tExtro
tCrypto
)
type
TxCallback
func
(
opType
OpType
)
bool
// Simple push/pop stack mechanism
type
Stack
struct
{
data
[]
*
big
.
Int
}
func
NewStack
()
*
Stack
{
return
&
Stack
{}
}
func
(
st
*
Stack
)
Data
()
[]
*
big
.
Int
{
return
st
.
data
}
func
(
st
*
Stack
)
Len
()
int
{
return
len
(
st
.
data
)
}
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
str
:=
st
.
data
[
len
(
st
.
data
)
-
1
]
copy
(
st
.
data
[
:
len
(
st
.
data
)
-
1
],
st
.
data
[
:
len
(
st
.
data
)
-
1
])
st
.
data
=
st
.
data
[
:
len
(
st
.
data
)
-
1
]
return
str
func
newStack
()
*
stack
{
return
&
stack
{}
}
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
ints
:=
st
.
data
[
len
(
st
.
data
)
-
2
:
]
copy
(
st
.
data
[
:
len
(
st
.
data
)
-
2
],
st
.
data
[
:
len
(
st
.
data
)
-
2
])
st
.
data
=
st
.
data
[
:
len
(
st
.
data
)
-
2
]
return
ints
[
0
],
ints
[
1
]
type
stack
struct
{
data
[]
*
big
.
Int
ptr
int
}
func
(
st
*
Stack
)
Peek
()
*
big
.
Int
{
str
:=
st
.
data
[
len
(
st
.
data
)
-
1
]
return
str
func
(
st
*
stack
)
push
(
d
*
big
.
Int
)
{
if
len
(
st
.
data
)
>
st
.
ptr
{
st
.
data
[
st
.
ptr
]
=
d
}
else
{
st
.
data
=
append
(
st
.
data
,
d
)
}
st
.
ptr
++
}
func
(
st
*
Stack
)
Peekn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
ints
:=
st
.
data
[
len
(
st
.
data
)
-
2
:
]
return
ints
[
0
],
ints
[
1
]
func
(
st
*
stack
)
pop
()
(
ret
*
big
.
Int
)
{
st
.
ptr
--
ret
=
st
.
data
[
st
.
ptr
]
return
}
func
(
st
*
Stack
)
Swapn
(
n
int
)
(
*
big
.
Int
,
*
big
.
Int
)
{
st
.
data
[
len
(
st
.
data
)
-
n
],
st
.
data
[
len
(
st
.
data
)
-
1
]
=
st
.
data
[
len
(
st
.
data
)
-
1
],
st
.
data
[
len
(
st
.
data
)
-
n
]
return
st
.
data
[
len
(
st
.
data
)
-
n
],
st
.
data
[
len
(
st
.
data
)
-
1
]
func
(
st
*
stack
)
len
()
int
{
return
st
.
ptr
}
func
(
st
*
Stack
)
Dupn
(
n
int
)
*
big
.
Int
{
st
.
Push
(
st
.
data
[
len
(
st
.
data
)
-
n
])
return
st
.
Peek
()
func
(
st
*
stack
)
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
*
Stack
)
Push
(
d
*
big
.
I
nt
)
{
st
.
data
=
append
(
st
.
data
,
new
(
big
.
Int
)
.
Set
(
d
)
)
func
(
st
*
stack
)
dup
(
n
i
nt
)
{
st
.
push
(
st
.
data
[
st
.
len
()
-
n
]
)
}
func
(
st
*
Stack
)
Get
(
amount
*
big
.
Int
)
[]
*
big
.
Int
{
// offset + size <= len(data)
length
:=
big
.
NewInt
(
int64
(
len
(
st
.
data
)))
if
amount
.
Cmp
(
length
)
<=
0
{
start
:=
new
(
big
.
Int
)
.
Sub
(
length
,
amount
)
return
st
.
data
[
start
.
Int64
()
:
length
.
Int64
()]
}
return
nil
func
(
st
*
stack
)
peek
()
*
big
.
Int
{
return
st
.
data
[
st
.
len
()
-
1
]
}
func
(
st
*
S
tack
)
require
(
n
int
)
{
if
st
.
L
en
()
<
n
{
panic
(
fmt
.
Sprintf
(
"stack underflow (%d <=> %d)"
,
st
.
Len
(
),
n
))
func
(
st
*
s
tack
)
require
(
n
int
)
{
if
st
.
l
en
()
<
n
{
panic
(
fmt
.
Sprintf
(
"stack underflow (%d <=> %d)"
,
len
(
st
.
data
),
n
))
}
}
func
(
st
*
S
tack
)
Print
()
{
func
(
st
*
s
tack
)
Print
()
{
fmt
.
Println
(
"### stack ###"
)
if
len
(
st
.
data
)
>
0
{
for
i
,
val
:=
range
st
.
data
{
...
...
@@ -107,72 +62,3 @@ func (st *Stack) Print() {
}
fmt
.
Println
(
"#############"
)
}
type
Memory
struct
{
store
[]
byte
}
func
NewMemory
()
*
Memory
{
return
&
Memory
{
nil
}
}
func
(
m
*
Memory
)
Set
(
offset
,
size
uint64
,
value
[]
byte
)
{
if
len
(
value
)
>
0
{
totSize
:=
offset
+
size
lenSize
:=
uint64
(
len
(
m
.
store
)
-
1
)
if
totSize
>
lenSize
{
// Calculate the diff between the sizes
diff
:=
totSize
-
lenSize
if
diff
>
0
{
// Create a new empty slice and append it
newSlice
:=
make
([]
byte
,
diff
-
1
)
// Resize slice
m
.
store
=
append
(
m
.
store
,
newSlice
...
)
}
}
copy
(
m
.
store
[
offset
:
offset
+
size
],
value
)
}
}
func
(
m
*
Memory
)
Resize
(
size
uint64
)
{
if
uint64
(
m
.
Len
())
<
size
{
m
.
store
=
append
(
m
.
store
,
make
([]
byte
,
size
-
uint64
(
m
.
Len
()))
...
)
}
}
func
(
self
*
Memory
)
Get
(
offset
,
size
int64
)
(
cpy
[]
byte
)
{
if
size
==
0
{
return
nil
}
if
len
(
self
.
store
)
>
int
(
offset
)
{
cpy
=
make
([]
byte
,
size
)
copy
(
cpy
,
self
.
store
[
offset
:
offset
+
size
])
return
}
return
}
func
(
m
*
Memory
)
Len
()
int
{
return
len
(
m
.
store
)
}
func
(
m
*
Memory
)
Data
()
[]
byte
{
return
m
.
store
}
func
(
m
*
Memory
)
Print
()
{
fmt
.
Printf
(
"### mem %d bytes ###
\n
"
,
len
(
m
.
store
))
if
len
(
m
.
store
)
>
0
{
addr
:=
0
for
i
:=
0
;
i
+
32
<=
len
(
m
.
store
);
i
+=
32
{
fmt
.
Printf
(
"%03d: % x
\n
"
,
addr
,
m
.
store
[
i
:
i
+
32
])
addr
++
}
}
else
{
fmt
.
Println
(
"-- empty --"
)
}
fmt
.
Println
(
"####################"
)
}
vm/vm.go
View file @
9007f2bb
...
...
@@ -19,8 +19,6 @@ type Vm struct {
// For logging
debug
bool
Dbg
Debugger
BreakPoints
[]
int64
Stepping
bool
Fn
string
...
...
@@ -66,10 +64,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
destinations
=
analyseJumpDests
(
context
.
Code
)
mem
=
NewMemory
()
stack
=
N
ewStack
()
stack
=
n
ewStack
()
pc
uint64
=
0
step
=
0
prevStep
=
0
statedb
=
self
.
env
.
State
()
jump
=
func
(
from
uint64
,
to
*
big
.
Int
)
{
...
...
@@ -93,7 +90,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
for
{
prevStep
=
step
// The base for all big integer arithmetic
base
:=
new
(
big
.
Int
)
...
...
@@ -101,11 +97,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
// Get the memory location of pc
op
=
context
.
GetOp
(
pc
)
self
.
Printf
(
"(pc) %-3d -o- %-14s (m) %-4d (s) %-4d "
,
pc
,
op
.
String
(),
mem
.
Len
(),
stack
.
Len
())
if
self
.
Dbg
!=
nil
{
//self.Dbg.Step(self, op, mem, stack, context)
}
self
.
Printf
(
"(pc) %-3d -o- %-14s (m) %-4d (s) %-4d "
,
pc
,
op
.
String
(),
mem
.
Len
(),
stack
.
len
())
newMemSize
,
gas
:=
self
.
calculateGasAndSize
(
context
,
caller
,
op
,
statedb
,
mem
,
stack
)
self
.
Printf
(
"(g) %-3v (%v)"
,
gas
,
context
.
Gas
)
...
...
@@ -125,40 +117,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
switch
op
{
// 0x20 range
case
ADD
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v + %v"
,
y
,
x
)
base
.
Add
(
y
,
x
)
base
.
Add
(
x
,
y
)
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
//
P
op result back on the stack
stack
.
P
ush
(
base
)
//
p
op result back on the stack
stack
.
p
ush
(
base
)
case
SUB
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v - %v"
,
y
,
x
)
base
.
Sub
(
y
,
x
)
base
.
Sub
(
x
,
y
)
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
//
P
op result back on the stack
stack
.
P
ush
(
base
)
//
p
op result back on the stack
stack
.
p
ush
(
base
)
case
MUL
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v * %v"
,
y
,
x
)
base
.
Mul
(
y
,
x
)
base
.
Mul
(
x
,
y
)
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
//
P
op result back on the stack
stack
.
P
ush
(
base
)
//
p
op result back on the stack
stack
.
p
ush
(
base
)
case
DIV
:
x
,
y
:=
stack
.
Pop
(),
stack
.
P
op
()
x
,
y
:=
stack
.
pop
(),
stack
.
p
op
()
self
.
Printf
(
" %v / %v"
,
x
,
y
)
if
y
.
Cmp
(
ethutil
.
Big0
)
!=
0
{
...
...
@@ -168,10 +160,10 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
//
P
op result back on the stack
stack
.
P
ush
(
base
)
//
p
op result back on the stack
stack
.
p
ush
(
base
)
case
SDIV
:
x
,
y
:=
S256
(
stack
.
Pop
()),
S256
(
stack
.
P
op
())
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
p
op
())
self
.
Printf
(
" %v / %v"
,
x
,
y
)
...
...
@@ -191,9 +183,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
self
.
Printf
(
" = %v"
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
MOD
:
x
,
y
:=
stack
.
Pop
(),
stack
.
P
op
()
x
,
y
:=
stack
.
pop
(),
stack
.
p
op
()
self
.
Printf
(
" %v %% %v"
,
x
,
y
)
...
...
@@ -206,9 +198,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
SMOD
:
x
,
y
:=
S256
(
stack
.
Pop
()),
S256
(
stack
.
P
op
())
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
p
op
())
self
.
Printf
(
" %v %% %v"
,
x
,
y
)
...
...
@@ -228,25 +220,25 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
self
.
Printf
(
" = %v"
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
EXP
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v ** %v"
,
y
,
x
)
self
.
Printf
(
" %v ** %v"
,
x
,
y
)
base
.
Exp
(
y
,
x
,
Pow256
)
base
.
Exp
(
x
,
y
,
Pow256
)
U256
(
base
)
self
.
Printf
(
" = %v"
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
SIGNEXTEND
:
back
:=
stack
.
P
op
()
.
Uint64
()
back
:=
stack
.
p
op
()
.
Uint64
()
if
back
<
31
{
bit
:=
uint
(
back
*
8
+
7
)
num
:=
stack
.
P
op
()
num
:=
stack
.
p
op
()
mask
:=
new
(
big
.
Int
)
.
Lsh
(
ethutil
.
Big1
,
bit
)
mask
.
Sub
(
mask
,
ethutil
.
Big1
)
if
ethutil
.
BitTest
(
num
,
int
(
bit
))
{
...
...
@@ -259,91 +251,91 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" = %v"
,
num
)
stack
.
P
ush
(
num
)
stack
.
p
ush
(
num
)
}
case
NOT
:
base
.
Sub
(
Pow256
,
stack
.
P
op
())
.
Sub
(
base
,
ethutil
.
Big1
)
base
.
Sub
(
Pow256
,
stack
.
p
op
())
.
Sub
(
base
,
ethutil
.
Big1
)
// Not needed
base
=
U256
(
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
LT
:
x
,
y
:=
stack
.
Popn
()
self
.
Printf
(
" %v < %v"
,
y
,
x
)
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v < %v"
,
x
,
y
)
// x < y
if
y
.
Cmp
(
x
)
<
0
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
if
x
.
Cmp
(
y
)
<
0
{
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
case
GT
:
x
,
y
:=
stack
.
Popn
()
self
.
Printf
(
" %v > %v"
,
y
,
x
)
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v > %v"
,
x
,
y
)
// x > y
if
y
.
Cmp
(
x
)
>
0
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
if
x
.
Cmp
(
y
)
>
0
{
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
case
SLT
:
y
,
x
:=
S256
(
stack
.
Pop
()),
S256
(
stack
.
P
op
())
self
.
Printf
(
" %v < %v"
,
y
,
x
)
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
p
op
())
self
.
Printf
(
" %v < %v"
,
x
,
y
)
// x < y
if
y
.
Cmp
(
S256
(
x
))
<
0
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
if
x
.
Cmp
(
S256
(
y
))
<
0
{
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
case
SGT
:
y
,
x
:=
S256
(
stack
.
Pop
()),
S256
(
stack
.
P
op
())
self
.
Printf
(
" %v > %v"
,
y
,
x
)
x
,
y
:=
S256
(
stack
.
pop
()),
S256
(
stack
.
p
op
())
self
.
Printf
(
" %v > %v"
,
x
,
y
)
// x > y
if
y
.
Cmp
(
x
)
>
0
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
if
x
.
Cmp
(
y
)
>
0
{
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
case
EQ
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v == %v"
,
y
,
x
)
// x == y
if
x
.
Cmp
(
y
)
==
0
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
case
ISZERO
:
x
:=
stack
.
P
op
()
x
:=
stack
.
p
op
()
if
x
.
Cmp
(
ethutil
.
BigFalse
)
>
0
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
stack
.
p
ush
(
ethutil
.
BigTrue
)
}
// 0x10 range
case
AND
:
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v & %v"
,
y
,
x
)
stack
.
Push
(
base
.
And
(
y
,
x
))
stack
.
push
(
base
.
And
(
x
,
y
))
case
OR
:
x
,
y
:=
stack
.
Popn
()
self
.
Printf
(
" %v | %v"
,
y
,
x
)
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v | %v"
,
x
,
y
)
stack
.
Push
(
base
.
Or
(
y
,
x
))
stack
.
push
(
base
.
Or
(
x
,
y
))
case
XOR
:
x
,
y
:=
stack
.
Popn
()
self
.
Printf
(
" %v ^ %v"
,
y
,
x
)
x
,
y
:=
stack
.
pop
(),
stack
.
pop
()
self
.
Printf
(
" %v ^ %v"
,
x
,
y
)
stack
.
Push
(
base
.
Xor
(
y
,
x
))
stack
.
push
(
base
.
Xor
(
x
,
y
))
case
BYTE
:
val
,
th
:=
stack
.
Popn
()
th
,
val
:=
stack
.
pop
(),
stack
.
pop
()
if
th
.
Cmp
(
big
.
NewInt
(
32
))
<
0
{
byt
:=
big
.
NewInt
(
int64
(
ethutil
.
LeftPadBytes
(
val
.
Bytes
(),
32
)[
th
.
Int64
()]))
...
...
@@ -355,12 +347,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" => 0x%x"
,
base
.
Bytes
())
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
ADDMOD
:
x
:=
stack
.
P
op
()
y
:=
stack
.
P
op
()
z
:=
stack
.
P
op
()
x
:=
stack
.
p
op
()
y
:=
stack
.
p
op
()
z
:=
stack
.
p
op
()
add
:=
new
(
big
.
Int
)
.
Add
(
x
,
y
)
if
len
(
z
.
Bytes
())
>
0
{
// NOT 0x0
...
...
@@ -371,12 +363,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" %v + %v %% %v = %v"
,
x
,
y
,
z
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
case
MULMOD
:
x
:=
stack
.
P
op
()
y
:=
stack
.
P
op
()
z
:=
stack
.
P
op
()
x
:=
stack
.
p
op
()
y
:=
stack
.
p
op
()
z
:=
stack
.
p
op
()
mul
:=
new
(
big
.
Int
)
.
Mul
(
x
,
y
)
if
len
(
z
.
Bytes
())
>
0
{
// NOT 0x0
...
...
@@ -387,24 +379,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" %v + %v %% %v = %v"
,
x
,
y
,
z
,
base
)
stack
.
P
ush
(
base
)
stack
.
p
ush
(
base
)
// 0x20 range
case
SHA3
:
size
,
offset
:=
stack
.
Popn
()
size
,
offset
:=
stack
.
pop
(),
stack
.
pop
()
data
:=
crypto
.
Sha3
(
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
()))
stack
.
P
ush
(
ethutil
.
BigD
(
data
))
stack
.
p
ush
(
ethutil
.
BigD
(
data
))
self
.
Printf
(
" => (%v) %x"
,
size
,
data
)
// 0x30 range
case
ADDRESS
:
stack
.
P
ush
(
ethutil
.
BigD
(
context
.
Address
()))
stack
.
p
ush
(
ethutil
.
BigD
(
context
.
Address
()))
self
.
Printf
(
" => %x"
,
context
.
Address
())
case
BALANCE
:
addr
:=
stack
.
P
op
()
.
Bytes
()
addr
:=
stack
.
p
op
()
.
Bytes
()
var
balance
*
big
.
Int
if
statedb
.
GetStateObject
(
addr
)
!=
nil
{
balance
=
statedb
.
GetBalance
(
addr
)
...
...
@@ -412,27 +404,27 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
balance
=
base
}
stack
.
P
ush
(
balance
)
stack
.
p
ush
(
balance
)
self
.
Printf
(
" => %v (%x)"
,
balance
,
addr
)
case
ORIGIN
:
origin
:=
self
.
env
.
Origin
()
stack
.
P
ush
(
ethutil
.
BigD
(
origin
))
stack
.
p
ush
(
ethutil
.
BigD
(
origin
))
self
.
Printf
(
" => %x"
,
origin
)
case
CALLER
:
caller
:=
context
.
caller
.
Address
()
stack
.
P
ush
(
ethutil
.
BigD
(
caller
))
stack
.
p
ush
(
ethutil
.
BigD
(
caller
))
self
.
Printf
(
" => %x"
,
caller
)
case
CALLVALUE
:
stack
.
P
ush
(
value
)
stack
.
p
ush
(
value
)
self
.
Printf
(
" => %v"
,
value
)
case
CALLDATALOAD
:
var
(
offset
=
stack
.
P
op
()
offset
=
stack
.
p
op
()
data
=
make
([]
byte
,
32
)
lenData
=
big
.
NewInt
(
int64
(
len
(
callData
)))
)
...
...
@@ -446,18 +438,18 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" => 0x%x"
,
data
)
stack
.
P
ush
(
ethutil
.
BigD
(
data
))
stack
.
p
ush
(
ethutil
.
BigD
(
data
))
case
CALLDATASIZE
:
l
:=
int64
(
len
(
callData
))
stack
.
P
ush
(
big
.
NewInt
(
l
))
stack
.
p
ush
(
big
.
NewInt
(
l
))
self
.
Printf
(
" => %d"
,
l
)
case
CALLDATACOPY
:
var
(
size
=
uint64
(
len
(
callData
))
mOff
=
stack
.
P
op
()
.
Uint64
()
cOff
=
stack
.
P
op
()
.
Uint64
()
l
=
stack
.
P
op
()
.
Uint64
()
mOff
=
stack
.
p
op
()
.
Uint64
()
cOff
=
stack
.
p
op
()
.
Uint64
()
l
=
stack
.
p
op
()
.
Uint64
()
)
if
cOff
>
size
{
...
...
@@ -475,7 +467,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
case
CODESIZE
,
EXTCODESIZE
:
var
code
[]
byte
if
op
==
EXTCODESIZE
{
addr
:=
stack
.
P
op
()
.
Bytes
()
addr
:=
stack
.
p
op
()
.
Bytes
()
code
=
statedb
.
GetCode
(
addr
)
}
else
{
...
...
@@ -483,21 +475,21 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
l
:=
big
.
NewInt
(
int64
(
len
(
code
)))
stack
.
P
ush
(
l
)
stack
.
p
ush
(
l
)
self
.
Printf
(
" => %d"
,
l
)
case
CODECOPY
,
EXTCODECOPY
:
var
code
[]
byte
if
op
==
EXTCODECOPY
{
code
=
statedb
.
GetCode
(
stack
.
P
op
()
.
Bytes
())
code
=
statedb
.
GetCode
(
stack
.
p
op
()
.
Bytes
())
}
else
{
code
=
context
.
Code
}
context
:=
NewContext
(
nil
,
nil
,
code
,
ethutil
.
Big0
,
ethutil
.
Big0
)
var
(
mOff
=
stack
.
P
op
()
.
Uint64
()
cOff
=
stack
.
P
op
()
.
Uint64
()
l
=
stack
.
P
op
()
.
Uint64
()
mOff
=
stack
.
p
op
()
.
Uint64
()
cOff
=
stack
.
p
op
()
.
Uint64
()
l
=
stack
.
p
op
()
.
Uint64
()
)
codeCopy
:=
context
.
GetCode
(
cOff
,
l
)
...
...
@@ -505,80 +497,80 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" => [%v, %v, %v] %x"
,
mOff
,
cOff
,
l
,
codeCopy
)
case
GASPRICE
:
stack
.
P
ush
(
context
.
Price
)
stack
.
p
ush
(
context
.
Price
)
self
.
Printf
(
" => %x"
,
context
.
Price
)
// 0x40 range
case
BLOCKHASH
:
num
:=
stack
.
P
op
()
num
:=
stack
.
p
op
()
n
:=
new
(
big
.
Int
)
.
Sub
(
self
.
env
.
BlockNumber
(),
ethutil
.
Big257
)
if
num
.
Cmp
(
n
)
>
0
&&
num
.
Cmp
(
self
.
env
.
BlockNumber
())
<
0
{
stack
.
P
ush
(
ethutil
.
BigD
(
self
.
env
.
GetHash
(
num
.
Uint64
())))
stack
.
p
ush
(
ethutil
.
BigD
(
self
.
env
.
GetHash
(
num
.
Uint64
())))
}
else
{
stack
.
P
ush
(
ethutil
.
Big0
)
stack
.
p
ush
(
ethutil
.
Big0
)
}
self
.
Printf
(
" => 0x%x"
,
stack
.
P
eek
()
.
Bytes
())
self
.
Printf
(
" => 0x%x"
,
stack
.
p
eek
()
.
Bytes
())
case
COINBASE
:
coinbase
:=
self
.
env
.
Coinbase
()
stack
.
P
ush
(
ethutil
.
BigD
(
coinbase
))
stack
.
p
ush
(
ethutil
.
BigD
(
coinbase
))
self
.
Printf
(
" => 0x%x"
,
coinbase
)
case
TIMESTAMP
:
time
:=
self
.
env
.
Time
()
stack
.
P
ush
(
big
.
NewInt
(
time
))
stack
.
p
ush
(
big
.
NewInt
(
time
))
self
.
Printf
(
" => 0x%x"
,
time
)
case
NUMBER
:
number
:=
self
.
env
.
BlockNumber
()
stack
.
P
ush
(
U256
(
number
))
stack
.
p
ush
(
U256
(
number
))
self
.
Printf
(
" => 0x%x"
,
number
.
Bytes
())
case
DIFFICULTY
:
difficulty
:=
self
.
env
.
Difficulty
()
stack
.
P
ush
(
difficulty
)
stack
.
p
ush
(
difficulty
)
self
.
Printf
(
" => 0x%x"
,
difficulty
.
Bytes
())
case
GASLIMIT
:
self
.
Printf
(
" => %v"
,
self
.
env
.
GasLimit
())
stack
.
P
ush
(
self
.
env
.
GasLimit
())
stack
.
p
ush
(
self
.
env
.
GasLimit
())
// 0x50 range
case
PUSH1
,
PUSH2
,
PUSH3
,
PUSH4
,
PUSH5
,
PUSH6
,
PUSH7
,
PUSH8
,
PUSH9
,
PUSH10
,
PUSH11
,
PUSH12
,
PUSH13
,
PUSH14
,
PUSH15
,
PUSH16
,
PUSH17
,
PUSH18
,
PUSH19
,
PUSH20
,
PUSH21
,
PUSH22
,
PUSH23
,
PUSH24
,
PUSH25
,
PUSH26
,
PUSH27
,
PUSH28
,
PUSH29
,
PUSH30
,
PUSH31
,
PUSH32
:
a
:=
uint64
(
op
-
PUSH1
+
1
)
byts
:=
context
.
GetRangeValue
(
pc
+
1
,
a
)
//
P
ush value to stack
stack
.
P
ush
(
ethutil
.
BigD
(
byts
))
//
p
ush value to stack
stack
.
p
ush
(
ethutil
.
BigD
(
byts
))
pc
+=
a
step
+=
int
(
op
)
-
int
(
PUSH1
)
+
1
self
.
Printf
(
" => 0x%x"
,
byts
)
case
POP
:
stack
.
P
op
()
stack
.
p
op
()
case
DUP1
,
DUP2
,
DUP3
,
DUP4
,
DUP5
,
DUP6
,
DUP7
,
DUP8
,
DUP9
,
DUP10
,
DUP11
,
DUP12
,
DUP13
,
DUP14
,
DUP15
,
DUP16
:
n
:=
int
(
op
-
DUP1
+
1
)
stack
.
Dupn
(
n
)
stack
.
dup
(
n
)
self
.
Printf
(
" => [%d] 0x%x"
,
n
,
stack
.
P
eek
()
.
Bytes
())
self
.
Printf
(
" => [%d] 0x%x"
,
n
,
stack
.
p
eek
()
.
Bytes
())
case
SWAP1
,
SWAP2
,
SWAP3
,
SWAP4
,
SWAP5
,
SWAP6
,
SWAP7
,
SWAP8
,
SWAP9
,
SWAP10
,
SWAP11
,
SWAP12
,
SWAP13
,
SWAP14
,
SWAP15
,
SWAP16
:
n
:=
int
(
op
-
SWAP1
+
2
)
x
,
y
:=
stack
.
Swapn
(
n
)
stack
.
swap
(
n
)
self
.
Printf
(
" => [%d]
%x [0] %x"
,
n
,
x
.
Bytes
(),
y
.
Bytes
()
)
self
.
Printf
(
" => [%d]
"
,
n
)
case
LOG0
,
LOG1
,
LOG2
,
LOG3
,
LOG4
:
n
:=
int
(
op
-
LOG0
)
topics
:=
make
([][]
byte
,
n
)
mS
ize
,
mStart
:=
stack
.
Popn
()
mS
tart
,
mSize
:=
stack
.
pop
(),
stack
.
pop
()
for
i
:=
0
;
i
<
n
;
i
++
{
topics
[
i
]
=
ethutil
.
LeftPadBytes
(
stack
.
P
op
()
.
Bytes
(),
32
)
topics
[
i
]
=
ethutil
.
LeftPadBytes
(
stack
.
p
op
()
.
Bytes
(),
32
)
}
data
:=
mem
.
Get
(
mStart
.
Int64
(),
mSize
.
Int64
())
...
...
@@ -587,41 +579,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self
.
Printf
(
" => %v"
,
log
)
case
MLOAD
:
offset
:=
stack
.
P
op
()
offset
:=
stack
.
p
op
()
val
:=
ethutil
.
BigD
(
mem
.
Get
(
offset
.
Int64
(),
32
))
stack
.
P
ush
(
val
)
stack
.
p
ush
(
val
)
self
.
Printf
(
" => 0x%x"
,
val
.
Bytes
())
case
MSTORE
:
// Store the value at stack top-1 in to memory at location stack top
//
P
op value of the stack
val
,
mStart
:=
stack
.
Popn
()
//
p
op value of the stack
mStart
,
val
:=
stack
.
pop
(),
stack
.
pop
()
mem
.
Set
(
mStart
.
Uint64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
self
.
Printf
(
" => 0x%x"
,
val
)
case
MSTORE8
:
off
:=
stack
.
Pop
()
val
:=
stack
.
Pop
()
off
,
val
:=
stack
.
pop
(),
stack
.
pop
()
mem
.
store
[
off
.
Int64
()]
=
byte
(
val
.
Int64
()
&
0xff
)
self
.
Printf
(
" => [%v] 0x%x"
,
off
,
val
)
case
SLOAD
:
loc
:=
stack
.
P
op
()
loc
:=
stack
.
p
op
()
val
:=
ethutil
.
BigD
(
statedb
.
GetState
(
context
.
Address
(),
loc
.
Bytes
()))
stack
.
P
ush
(
val
)
stack
.
p
ush
(
val
)
self
.
Printf
(
" {0x%x : 0x%x}"
,
loc
.
Bytes
(),
val
.
Bytes
())
case
SSTORE
:
val
,
loc
:=
stack
.
Popn
()
loc
,
val
:=
stack
.
pop
(),
stack
.
pop
()
statedb
.
SetState
(
context
.
Address
(),
loc
.
Bytes
(),
val
)
self
.
Printf
(
" {0x%x : 0x%x}"
,
loc
.
Bytes
(),
val
.
Bytes
())
case
JUMP
:
jump
(
pc
,
stack
.
P
op
())
jump
(
pc
,
stack
.
p
op
())
continue
case
JUMPI
:
cond
,
pos
:=
stack
.
Popn
()
pos
,
cond
:=
stack
.
pop
(),
stack
.
pop
()
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
{
jump
(
pc
,
pos
)
...
...
@@ -633,19 +624,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
case
JUMPDEST
:
case
PC
:
stack
.
P
ush
(
big
.
NewInt
(
int64
(
pc
)))
stack
.
p
ush
(
big
.
NewInt
(
int64
(
pc
)))
case
MSIZE
:
stack
.
P
ush
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
stack
.
p
ush
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
case
GAS
:
stack
.
P
ush
(
context
.
Gas
)
stack
.
p
ush
(
context
.
Gas
)
self
.
Printf
(
" => %x"
,
context
.
Gas
)
// 0x60 range
case
CREATE
:
var
(
value
=
stack
.
P
op
()
size
,
offset
=
stack
.
Popn
()
value
=
stack
.
p
op
()
offset
,
size
=
stack
.
pop
(),
stack
.
pop
()
input
=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
gas
=
new
(
big
.
Int
)
.
Set
(
context
.
Gas
)
addr
[]
byte
...
...
@@ -655,7 +646,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
context
.
UseGas
(
context
.
Gas
)
ret
,
suberr
,
ref
:=
self
.
env
.
Create
(
context
,
nil
,
input
,
gas
,
price
,
value
)
if
suberr
!=
nil
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
self
.
Printf
(
" (*) 0x0 %v"
,
suberr
)
}
else
{
...
...
@@ -668,23 +659,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
addr
=
ref
.
Address
()
stack
.
P
ush
(
ethutil
.
BigD
(
addr
))
stack
.
p
ush
(
ethutil
.
BigD
(
addr
))
}
// Debug hook
if
self
.
Dbg
!=
nil
{
self
.
Dbg
.
SetCode
(
context
.
Code
)
}
case
CALL
,
CALLCODE
:
gas
:=
stack
.
P
op
()
//
P
op gas and value of the stack.
value
,
addr
:=
stack
.
Popn
()
gas
:=
stack
.
p
op
()
//
p
op gas and value of the stack.
addr
,
value
:=
stack
.
pop
(),
stack
.
pop
()
value
=
U256
(
value
)
//
P
op input size and offset
in
Size
,
inOffset
:=
stack
.
Popn
()
//
P
op return size and offset
ret
Size
,
retOffset
:=
stack
.
Popn
()
//
p
op input size and offset
in
Offset
,
inSize
:=
stack
.
pop
(),
stack
.
pop
()
//
p
op return size and offset
ret
Offset
,
retSize
:=
stack
.
pop
(),
stack
.
pop
()
address
:=
ethutil
.
Address
(
addr
.
Bytes
())
self
.
Printf
(
" => %x"
,
address
)
.
Endl
()
...
...
@@ -707,30 +694,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
if
err
!=
nil
{
stack
.
P
ush
(
ethutil
.
BigFalse
)
stack
.
p
ush
(
ethutil
.
BigFalse
)
vmlogger
.
Debugln
(
err
)
}
else
{
stack
.
P
ush
(
ethutil
.
BigTrue
)
stack
.
p
ush
(
ethutil
.
BigTrue
)
mem
.
Set
(
retOffset
.
Uint64
(),
retSize
.
Uint64
(),
ret
)
}
self
.
Printf
(
"resume %x (%v)"
,
context
.
Address
(),
context
.
Gas
)
// Debug hook
if
self
.
Dbg
!=
nil
{
self
.
Dbg
.
SetCode
(
context
.
Code
)
}
case
RETURN
:
size
,
offset
:=
stack
.
Popn
()
offset
,
size
:=
stack
.
pop
(),
stack
.
pop
()
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
self
.
Printf
(
" => [%v, %v] (%d) 0x%x"
,
offset
,
size
,
len
(
ret
),
ret
)
.
Endl
()
return
context
.
Return
(
ret
),
nil
case
SUICIDE
:
receiver
:=
statedb
.
GetOrNewStateObject
(
stack
.
P
op
()
.
Bytes
())
receiver
:=
statedb
.
GetOrNewStateObject
(
stack
.
p
op
()
.
Bytes
())
balance
:=
statedb
.
GetBalance
(
context
.
Address
())
self
.
Printf
(
" => (%x) %v"
,
receiver
.
Address
()[
:
4
],
balance
)
...
...
@@ -753,117 +734,17 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
pc
++
self
.
Endl
()
if
self
.
Dbg
!=
nil
{
for
_
,
instrNo
:=
range
self
.
Dbg
.
BreakPoints
()
{
if
pc
==
uint64
(
instrNo
)
{
self
.
Stepping
=
true
if
!
self
.
Dbg
.
BreakHook
(
prevStep
,
op
,
mem
,
stack
,
statedb
.
GetStateObject
(
context
.
Address
()))
{
return
nil
,
nil
}
}
else
if
self
.
Stepping
{
if
!
self
.
Dbg
.
StepHook
(
prevStep
,
op
,
mem
,
stack
,
statedb
.
GetStateObject
(
context
.
Address
()))
{
return
nil
,
nil
}
}
}
}
}
}
type
req
struct
{
stack
int
gas
*
big
.
Int
}
var
_baseCheck
=
map
[
OpCode
]
req
{
// Req Stack Gas price
ADD
:
{
2
,
GasFastestStep
},
LT
:
{
2
,
GasFastestStep
},
GT
:
{
2
,
GasFastestStep
},
SLT
:
{
2
,
GasFastestStep
},
SGT
:
{
2
,
GasFastestStep
},
EQ
:
{
2
,
GasFastestStep
},
ISZERO
:
{
1
,
GasFastestStep
},
SUB
:
{
2
,
GasFastestStep
},
AND
:
{
2
,
GasFastestStep
},
OR
:
{
2
,
GasFastestStep
},
XOR
:
{
2
,
GasFastestStep
},
NOT
:
{
1
,
GasFastestStep
},
BYTE
:
{
2
,
GasFastestStep
},
CALLDATALOAD
:
{
1
,
GasFastestStep
},
CALLDATACOPY
:
{
3
,
GasFastestStep
},
MLOAD
:
{
1
,
GasFastestStep
},
MSTORE
:
{
2
,
GasFastestStep
},
MSTORE8
:
{
2
,
GasFastestStep
},
CODECOPY
:
{
3
,
GasFastestStep
},
MUL
:
{
2
,
GasFastStep
},
DIV
:
{
2
,
GasFastStep
},
SDIV
:
{
2
,
GasFastStep
},
MOD
:
{
2
,
GasFastStep
},
SMOD
:
{
2
,
GasFastStep
},
SIGNEXTEND
:
{
2
,
GasFastStep
},
ADDMOD
:
{
3
,
GasMidStep
},
MULMOD
:
{
3
,
GasMidStep
},
JUMP
:
{
1
,
GasMidStep
},
JUMPI
:
{
2
,
GasSlowStep
},
EXP
:
{
2
,
GasSlowStep
},
ADDRESS
:
{
0
,
GasQuickStep
},
ORIGIN
:
{
0
,
GasQuickStep
},
CALLER
:
{
0
,
GasQuickStep
},
CALLVALUE
:
{
0
,
GasQuickStep
},
CODESIZE
:
{
0
,
GasQuickStep
},
GASPRICE
:
{
0
,
GasQuickStep
},
COINBASE
:
{
0
,
GasQuickStep
},
TIMESTAMP
:
{
0
,
GasQuickStep
},
NUMBER
:
{
0
,
GasQuickStep
},
CALLDATASIZE
:
{
0
,
GasQuickStep
},
DIFFICULTY
:
{
0
,
GasQuickStep
},
GASLIMIT
:
{
0
,
GasQuickStep
},
POP
:
{
0
,
GasQuickStep
},
PC
:
{
0
,
GasQuickStep
},
MSIZE
:
{
0
,
GasQuickStep
},
GAS
:
{
0
,
GasQuickStep
},
BLOCKHASH
:
{
1
,
GasExtStep
},
BALANCE
:
{
0
,
GasExtStep
},
EXTCODESIZE
:
{
1
,
GasExtStep
},
EXTCODECOPY
:
{
4
,
GasExtStep
},
SLOAD
:
{
1
,
GasStorageGet
},
SSTORE
:
{
2
,
Zero
},
SHA3
:
{
1
,
GasSha3Base
},
CREATE
:
{
3
,
GasCreate
},
CALL
:
{
7
,
GasCall
},
CALLCODE
:
{
7
,
GasCall
},
JUMPDEST
:
{
0
,
GasJumpDest
},
SUICIDE
:
{
1
,
Zero
},
RETURN
:
{
2
,
Zero
},
}
func
baseCheck
(
op
OpCode
,
stack
*
Stack
,
gas
*
big
.
Int
)
{
if
r
,
ok
:=
_baseCheck
[
op
];
ok
{
stack
.
require
(
r
.
stack
)
gas
.
Add
(
gas
,
r
.
gas
)
}
}
func
toWordSize
(
size
*
big
.
Int
)
*
big
.
Int
{
tmp
:=
new
(
big
.
Int
)
tmp
.
Add
(
size
,
u256
(
31
))
tmp
.
Div
(
tmp
,
u256
(
32
))
return
tmp
}
func
(
self
*
Vm
)
calculateGasAndSize
(
context
*
Context
,
caller
ContextRef
,
op
OpCode
,
statedb
*
state
.
StateDB
,
mem
*
Memory
,
stack
*
Stack
)
(
*
big
.
Int
,
*
big
.
Int
)
{
func
(
self
*
Vm
)
calculateGasAndSize
(
context
*
Context
,
caller
ContextRef
,
op
OpCode
,
statedb
*
state
.
StateDB
,
mem
*
Memory
,
stack
*
stack
)
(
*
big
.
Int
,
*
big
.
Int
)
{
var
(
gas
=
new
(
big
.
Int
)
newMemSize
*
big
.
Int
=
new
(
big
.
Int
)
)
baseCheck
(
op
,
stack
,
gas
)
//
S
tack Check, memory resize & gas phase
//
s
tack Check, memory resize & gas phase
switch
op
{
case
PUSH1
,
PUSH2
,
PUSH3
,
PUSH4
,
PUSH5
,
PUSH6
,
PUSH7
,
PUSH8
,
PUSH9
,
PUSH10
,
PUSH11
,
PUSH12
,
PUSH13
,
PUSH14
,
PUSH15
,
PUSH16
,
PUSH17
,
PUSH18
,
PUSH19
,
PUSH20
,
PUSH21
,
PUSH22
,
PUSH23
,
PUSH24
,
PUSH25
,
PUSH26
,
PUSH27
,
PUSH28
,
PUSH29
,
PUSH30
,
PUSH31
,
PUSH32
:
gas
.
Set
(
GasFastestStep
)
...
...
@@ -879,7 +760,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
n
:=
int
(
op
-
LOG0
)
stack
.
require
(
n
+
2
)
mSize
,
mStart
:=
stack
.
Peekn
()
mSize
,
mStart
:=
stack
.
data
[
stack
.
len
()
-
2
],
stack
.
data
[
stack
.
len
()
-
1
]
gas
.
Add
(
gas
,
GasLogBase
)
gas
.
Add
(
gas
,
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
int64
(
n
)),
GasLogTopic
))
...
...
@@ -887,12 +768,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize
=
calcMemSize
(
mStart
,
mSize
)
case
EXP
:
gas
.
Add
(
gas
,
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
int64
(
len
(
stack
.
data
[
stack
.
L
en
()
-
2
]
.
Bytes
()))),
GasExpByte
))
gas
.
Add
(
gas
,
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
int64
(
len
(
stack
.
data
[
stack
.
l
en
()
-
2
]
.
Bytes
()))),
GasExpByte
))
case
SSTORE
:
stack
.
require
(
2
)
var
g
*
big
.
Int
y
,
x
:=
stack
.
Peekn
()
y
,
x
:=
stack
.
data
[
stack
.
len
()
-
2
],
stack
.
data
[
stack
.
len
()
-
1
]
val
:=
statedb
.
GetState
(
context
.
Address
(),
x
.
Bytes
())
if
len
(
val
)
==
0
&&
len
(
y
.
Bytes
())
>
0
{
// 0 => non 0
...
...
@@ -911,51 +792,51 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
statedb
.
Refund
(
self
.
env
.
Origin
(),
RefundSuicide
)
}
case
MLOAD
:
newMemSize
=
calcMemSize
(
stack
.
P
eek
(),
u256
(
32
))
newMemSize
=
calcMemSize
(
stack
.
p
eek
(),
u256
(
32
))
case
MSTORE8
:
newMemSize
=
calcMemSize
(
stack
.
P
eek
(),
u256
(
1
))
newMemSize
=
calcMemSize
(
stack
.
p
eek
(),
u256
(
1
))
case
MSTORE
:
newMemSize
=
calcMemSize
(
stack
.
P
eek
(),
u256
(
32
))
newMemSize
=
calcMemSize
(
stack
.
p
eek
(),
u256
(
32
))
case
RETURN
:
newMemSize
=
calcMemSize
(
stack
.
Peek
(),
stack
.
data
[
stack
.
L
en
()
-
2
])
newMemSize
=
calcMemSize
(
stack
.
peek
(),
stack
.
data
[
stack
.
l
en
()
-
2
])
case
SHA3
:
newMemSize
=
calcMemSize
(
stack
.
Peek
(),
stack
.
data
[
stack
.
L
en
()
-
2
])
newMemSize
=
calcMemSize
(
stack
.
peek
(),
stack
.
data
[
stack
.
l
en
()
-
2
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
L
en
()
-
2
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
l
en
()
-
2
])
gas
.
Add
(
gas
,
words
.
Mul
(
words
,
GasSha3Word
))
case
CALLDATACOPY
:
newMemSize
=
calcMemSize
(
stack
.
Peek
(),
stack
.
data
[
stack
.
L
en
()
-
3
])
newMemSize
=
calcMemSize
(
stack
.
peek
(),
stack
.
data
[
stack
.
l
en
()
-
3
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
L
en
()
-
3
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
l
en
()
-
3
])
gas
.
Add
(
gas
,
words
.
Mul
(
words
,
GasCopyWord
))
case
CODECOPY
:
newMemSize
=
calcMemSize
(
stack
.
Peek
(),
stack
.
data
[
stack
.
L
en
()
-
3
])
newMemSize
=
calcMemSize
(
stack
.
peek
(),
stack
.
data
[
stack
.
l
en
()
-
3
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
L
en
()
-
3
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
l
en
()
-
3
])
gas
.
Add
(
gas
,
words
.
Mul
(
words
,
GasCopyWord
))
case
EXTCODECOPY
:
newMemSize
=
calcMemSize
(
stack
.
data
[
stack
.
Len
()
-
2
],
stack
.
data
[
stack
.
L
en
()
-
4
])
newMemSize
=
calcMemSize
(
stack
.
data
[
stack
.
len
()
-
2
],
stack
.
data
[
stack
.
l
en
()
-
4
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
L
en
()
-
4
])
words
:=
toWordSize
(
stack
.
data
[
stack
.
l
en
()
-
4
])
gas
.
Add
(
gas
,
words
.
Mul
(
words
,
GasCopyWord
))
case
CREATE
:
newMemSize
=
calcMemSize
(
stack
.
data
[
stack
.
Len
()
-
2
],
stack
.
data
[
stack
.
L
en
()
-
3
])
newMemSize
=
calcMemSize
(
stack
.
data
[
stack
.
len
()
-
2
],
stack
.
data
[
stack
.
l
en
()
-
3
])
case
CALL
,
CALLCODE
:
gas
.
Add
(
gas
,
stack
.
data
[
stack
.
L
en
()
-
1
])
gas
.
Add
(
gas
,
stack
.
data
[
stack
.
l
en
()
-
1
])
if
op
==
CALL
{
if
self
.
env
.
State
()
.
GetStateObject
(
stack
.
data
[
stack
.
L
en
()
-
2
]
.
Bytes
())
==
nil
{
if
self
.
env
.
State
()
.
GetStateObject
(
stack
.
data
[
stack
.
l
en
()
-
2
]
.
Bytes
())
==
nil
{
gas
.
Add
(
gas
,
GasCallNewAccount
)
}
}
if
len
(
stack
.
data
[
stack
.
L
en
()
-
3
]
.
Bytes
())
>
0
{
if
len
(
stack
.
data
[
stack
.
l
en
()
-
3
]
.
Bytes
())
>
0
{
gas
.
Add
(
gas
,
GasCallValueTransfer
)
}
x
:=
calcMemSize
(
stack
.
data
[
stack
.
Len
()
-
6
],
stack
.
data
[
stack
.
L
en
()
-
7
])
y
:=
calcMemSize
(
stack
.
data
[
stack
.
Len
()
-
4
],
stack
.
data
[
stack
.
L
en
()
-
5
])
x
:=
calcMemSize
(
stack
.
data
[
stack
.
len
()
-
6
],
stack
.
data
[
stack
.
l
en
()
-
7
])
y
:=
calcMemSize
(
stack
.
data
[
stack
.
len
()
-
4
],
stack
.
data
[
stack
.
l
en
()
-
5
])
newMemSize
=
ethutil
.
BigMax
(
x
,
y
)
}
...
...
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