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
ca13e3b1
Commit
ca13e3b1
authored
Apr 15, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved assembler stage processing to it's own file
parent
086acd12
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
430 additions
and
213 deletions
+430
-213
asm.go
ethchain/asm.go
+126
-0
closure.go
ethchain/closure.go
+1
-1
stack.go
ethchain/stack.go
+4
-147
types.go
ethchain/types.go
+230
-0
vm.go
ethchain/vm.go
+69
-65
No files found.
ethchain/asm.go
0 → 100644
View file @
ca13e3b1
package
ethchain
import
(
"fmt"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"regexp"
)
func
CompileInstr
(
s
interface
{})
([]
byte
,
error
)
{
switch
s
.
(
type
)
{
case
string
:
str
:=
s
.
(
string
)
isOp
:=
IsOpCode
(
str
)
if
isOp
{
return
[]
byte
{
OpCodes
[
str
]},
nil
}
num
:=
new
(
big
.
Int
)
_
,
success
:=
num
.
SetString
(
str
,
0
)
// Assume regular bytes during compilation
if
!
success
{
num
.
SetBytes
([]
byte
(
str
))
}
else
{
// tmp fix for 32 bytes
n
:=
ethutil
.
BigToBytes
(
num
,
256
)
return
n
,
nil
}
return
num
.
Bytes
(),
nil
case
int
:
num
:=
ethutil
.
BigToBytes
(
big
.
NewInt
(
int64
(
s
.
(
int
))),
256
)
return
num
,
nil
case
[]
byte
:
return
ethutil
.
BigD
(
s
.
([]
byte
))
.
Bytes
(),
nil
}
return
nil
,
nil
}
// Script compilation functions
// Compiles strings to machine code
func
Assemble
(
instructions
...
interface
{})
(
script
[]
byte
)
{
//script = make([]string, len(instructions))
for
_
,
val
:=
range
instructions
{
instr
,
_
:=
CompileInstr
(
val
)
//script[i] = string(instr)
script
=
append
(
script
,
instr
...
)
}
return
}
func
Disassemble
(
script
[]
byte
)
(
asm
[]
string
)
{
pc
:=
new
(
big
.
Int
)
for
{
if
pc
.
Cmp
(
big
.
NewInt
(
int64
(
len
(
script
))))
>=
0
{
return
}
// Get the memory location of pc
val
:=
script
[
pc
.
Int64
()]
// Get the opcode (it must be an opcode!)
op
:=
OpCode
(
val
)
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"%v"
,
op
))
switch
op
{
case
oPUSH
:
// Push PC+1 on to the stack
pc
.
Add
(
pc
,
ethutil
.
Big1
)
data
:=
script
[
pc
.
Int64
()
:
pc
.
Int64
()
+
32
]
val
:=
ethutil
.
BigD
(
data
)
var
b
[]
byte
if
val
.
Int64
()
==
0
{
b
=
[]
byte
{
0
}
}
else
{
b
=
val
.
Bytes
()
}
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"0x%x"
,
b
))
pc
.
Add
(
pc
,
big
.
NewInt
(
31
))
case
oPUSH20
:
pc
.
Add
(
pc
,
ethutil
.
Big1
)
data
:=
script
[
pc
.
Int64
()
:
pc
.
Int64
()
+
20
]
val
:=
ethutil
.
BigD
(
data
)
var
b
[]
byte
if
val
.
Int64
()
==
0
{
b
=
[]
byte
{
0
}
}
else
{
b
=
val
.
Bytes
()
}
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"0x%x"
,
b
))
pc
.
Add
(
pc
,
big
.
NewInt
(
19
))
}
pc
.
Add
(
pc
,
ethutil
.
Big1
)
}
return
}
func
PreProcess
(
data
string
)
(
mainInput
,
initInput
string
)
{
reg
:=
"
\\
(
\\
)
\\
s*{([
\\
d
\\
w
\\
W
\\
n
\\
s]+?)}"
mainReg
:=
regexp
.
MustCompile
(
"main"
+
reg
)
initReg
:=
regexp
.
MustCompile
(
"init"
+
reg
)
main
:=
mainReg
.
FindStringSubmatch
(
data
)
if
len
(
main
)
>
0
{
mainInput
=
main
[
1
]
}
else
{
mainInput
=
data
}
init
:=
initReg
.
FindStringSubmatch
(
data
)
if
len
(
init
)
>
0
{
initInput
=
init
[
1
]
}
return
}
ethchain/closure.go
View file @
ca13e3b1
...
@@ -71,7 +71,7 @@ func (c *Closure) Address() []byte {
...
@@ -71,7 +71,7 @@ func (c *Closure) Address() []byte {
type
DebugHook
func
(
step
int
,
op
OpCode
,
mem
*
Memory
,
stack
*
Stack
)
type
DebugHook
func
(
step
int
,
op
OpCode
,
mem
*
Memory
,
stack
*
Stack
)
func
(
c
*
Closure
)
Call
(
vm
*
Vm
,
args
[]
byte
,
hook
DebugHook
)
[]
byte
{
func
(
c
*
Closure
)
Call
(
vm
*
Vm
,
args
[]
byte
,
hook
DebugHook
)
([]
byte
,
error
)
{
c
.
Args
=
args
c
.
Args
=
args
return
vm
.
RunClosure
(
c
,
hook
)
return
vm
.
RunClosure
(
c
,
hook
)
...
...
ethchain/stack.go
View file @
ca13e3b1
...
@@ -6,153 +6,6 @@ import (
...
@@ -6,153 +6,6 @@ import (
"math/big"
"math/big"
)
)
type
OpCode
int
// Op codes
const
(
// 0x0 range - arithmetic ops
oSTOP
=
0x00
oADD
=
0x01
oMUL
=
0x02
oSUB
=
0x03
oDIV
=
0x04
oSDIV
=
0x05
oMOD
=
0x06
oSMOD
=
0x07
oEXP
=
0x08
oNEG
=
0x09
oLT
=
0x0a
oGT
=
0x0b
oEQ
=
0x0c
oNOT
=
0x0d
// 0x10 range - bit ops
oAND
=
0x10
oOR
=
0x11
oXOR
=
0x12
oBYTE
=
0x13
// 0x20 range - crypto
oSHA3
=
0x20
// 0x30 range - closure state
oADDRESS
=
0x30
oBALANCE
=
0x31
oORIGIN
=
0x32
oCALLER
=
0x33
oCALLVALUE
=
0x34
oCALLDATA
=
0x35
oCALLDATASIZE
=
0x36
oGASPRICE
=
0x37
// 0x40 range - block operations
oPREVHASH
=
0x40
oCOINBASE
=
0x41
oTIMESTAMP
=
0x42
oNUMBER
=
0x43
oDIFFICULTY
=
0x44
oGASLIMIT
=
0x45
// 0x50 range - 'storage' and execution
oPUSH
=
0x50
oPUSH20
=
0x80
oPOP
=
0x51
oDUP
=
0x52
oSWAP
=
0x53
oMLOAD
=
0x54
oMSTORE
=
0x55
oMSTORE8
=
0x56
oSLOAD
=
0x57
oSSTORE
=
0x58
oJUMP
=
0x59
oJUMPI
=
0x5a
oPC
=
0x5b
oMSIZE
=
0x5c
// 0x60 range - closures
oCREATE
=
0x60
oCALL
=
0x61
oRETURN
=
0x62
// 0x70 range - other
oLOG
=
0x70
// XXX Unofficial
oSUICIDE
=
0x7f
)
// Since the opcodes aren't all in order we can't use a regular slice
var
opCodeToString
=
map
[
OpCode
]
string
{
// 0x0 range - arithmetic ops
oSTOP
:
"STOP"
,
oADD
:
"ADD"
,
oMUL
:
"MUL"
,
oSUB
:
"SUB"
,
oDIV
:
"DIV"
,
oSDIV
:
"SDIV"
,
oMOD
:
"MOD"
,
oSMOD
:
"SMOD"
,
oEXP
:
"EXP"
,
oNEG
:
"NEG"
,
oLT
:
"LT"
,
oGT
:
"GT"
,
oEQ
:
"EQ"
,
oNOT
:
"NOT"
,
// 0x10 range - bit ops
oAND
:
"AND"
,
oOR
:
"OR"
,
oXOR
:
"XOR"
,
oBYTE
:
"BYTE"
,
// 0x20 range - crypto
oSHA3
:
"SHA3"
,
// 0x30 range - closure state
oADDRESS
:
"ADDRESS"
,
oBALANCE
:
"BALANCE"
,
oORIGIN
:
"ORIGIN"
,
oCALLER
:
"CALLER"
,
oCALLVALUE
:
"CALLVALUE"
,
oCALLDATA
:
"CALLDATA"
,
oCALLDATASIZE
:
"CALLDATASIZE"
,
oGASPRICE
:
"TXGASPRICE"
,
// 0x40 range - block operations
oPREVHASH
:
"PREVHASH"
,
oCOINBASE
:
"COINBASE"
,
oTIMESTAMP
:
"TIMESTAMP"
,
oNUMBER
:
"NUMBER"
,
oDIFFICULTY
:
"DIFFICULTY"
,
oGASLIMIT
:
"GASLIMIT"
,
// 0x50 range - 'storage' and execution
oPUSH
:
"PUSH"
,
oPOP
:
"POP"
,
oDUP
:
"DUP"
,
oSWAP
:
"SWAP"
,
oMLOAD
:
"MLOAD"
,
oMSTORE
:
"MSTORE"
,
oMSTORE8
:
"MSTORE8"
,
oSLOAD
:
"SLOAD"
,
oSSTORE
:
"SSTORE"
,
oJUMP
:
"JUMP"
,
oJUMPI
:
"JUMPI"
,
oPC
:
"PC"
,
oMSIZE
:
"MSIZE"
,
// 0x60 range - closures
oCREATE
:
"CREATE"
,
oCALL
:
"CALL"
,
oRETURN
:
"RETURN"
,
// 0x70 range - other
oLOG
:
"LOG"
,
oSUICIDE
:
"SUICIDE"
,
}
func
(
o
OpCode
)
String
()
string
{
return
opCodeToString
[
o
]
}
type
OpType
int
type
OpType
int
const
(
const
(
...
@@ -177,6 +30,10 @@ func (st *Stack) Data() []*big.Int {
...
@@ -177,6 +30,10 @@ func (st *Stack) Data() []*big.Int {
return
st
.
data
return
st
.
data
}
}
func
(
st
*
Stack
)
Len
()
int
{
return
len
(
st
.
data
)
}
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
str
:=
st
.
data
[
len
(
st
.
data
)
-
1
]
str
:=
st
.
data
[
len
(
st
.
data
)
-
1
]
...
...
ethchain/types.go
0 → 100644
View file @
ca13e3b1
package
ethchain
type
OpCode
int
// Op codes
const
(
// 0x0 range - arithmetic ops
oSTOP
=
0x00
oADD
=
0x01
oMUL
=
0x02
oSUB
=
0x03
oDIV
=
0x04
oSDIV
=
0x05
oMOD
=
0x06
oSMOD
=
0x07
oEXP
=
0x08
oNEG
=
0x09
oLT
=
0x0a
oGT
=
0x0b
oEQ
=
0x0c
oNOT
=
0x0d
// 0x10 range - bit ops
oAND
=
0x10
oOR
=
0x11
oXOR
=
0x12
oBYTE
=
0x13
// 0x20 range - crypto
oSHA3
=
0x20
// 0x30 range - closure state
oADDRESS
=
0x30
oBALANCE
=
0x31
oORIGIN
=
0x32
oCALLER
=
0x33
oCALLVALUE
=
0x34
oCALLDATA
=
0x35
oCALLDATASIZE
=
0x36
oGASPRICE
=
0x37
// 0x40 range - block operations
oPREVHASH
=
0x40
oCOINBASE
=
0x41
oTIMESTAMP
=
0x42
oNUMBER
=
0x43
oDIFFICULTY
=
0x44
oGASLIMIT
=
0x45
// 0x50 range - 'storage' and execution
oPUSH
=
0x50
oPUSH20
=
0x80
oPOP
=
0x51
oDUP
=
0x52
oSWAP
=
0x53
oMLOAD
=
0x54
oMSTORE
=
0x55
oMSTORE8
=
0x56
oSLOAD
=
0x57
oSSTORE
=
0x58
oJUMP
=
0x59
oJUMPI
=
0x5a
oPC
=
0x5b
oMSIZE
=
0x5c
// 0x60 range - closures
oCREATE
=
0x60
oCALL
=
0x61
oRETURN
=
0x62
// 0x70 range - other
oLOG
=
0x70
// XXX Unofficial
oSUICIDE
=
0x7f
)
// Since the opcodes aren't all in order we can't use a regular slice
var
opCodeToString
=
map
[
OpCode
]
string
{
// 0x0 range - arithmetic ops
oSTOP
:
"STOP"
,
oADD
:
"ADD"
,
oMUL
:
"MUL"
,
oSUB
:
"SUB"
,
oDIV
:
"DIV"
,
oSDIV
:
"SDIV"
,
oMOD
:
"MOD"
,
oSMOD
:
"SMOD"
,
oEXP
:
"EXP"
,
oNEG
:
"NEG"
,
oLT
:
"LT"
,
oGT
:
"GT"
,
oEQ
:
"EQ"
,
oNOT
:
"NOT"
,
// 0x10 range - bit ops
oAND
:
"AND"
,
oOR
:
"OR"
,
oXOR
:
"XOR"
,
oBYTE
:
"BYTE"
,
// 0x20 range - crypto
oSHA3
:
"SHA3"
,
// 0x30 range - closure state
oADDRESS
:
"ADDRESS"
,
oBALANCE
:
"BALANCE"
,
oORIGIN
:
"ORIGIN"
,
oCALLER
:
"CALLER"
,
oCALLVALUE
:
"CALLVALUE"
,
oCALLDATA
:
"CALLDATA"
,
oCALLDATASIZE
:
"CALLDATASIZE"
,
oGASPRICE
:
"TXGASPRICE"
,
// 0x40 range - block operations
oPREVHASH
:
"PREVHASH"
,
oCOINBASE
:
"COINBASE"
,
oTIMESTAMP
:
"TIMESTAMP"
,
oNUMBER
:
"NUMBER"
,
oDIFFICULTY
:
"DIFFICULTY"
,
oGASLIMIT
:
"GASLIMIT"
,
// 0x50 range - 'storage' and execution
oPUSH
:
"PUSH"
,
oPOP
:
"POP"
,
oDUP
:
"DUP"
,
oSWAP
:
"SWAP"
,
oMLOAD
:
"MLOAD"
,
oMSTORE
:
"MSTORE"
,
oMSTORE8
:
"MSTORE8"
,
oSLOAD
:
"SLOAD"
,
oSSTORE
:
"SSTORE"
,
oJUMP
:
"JUMP"
,
oJUMPI
:
"JUMPI"
,
oPC
:
"PC"
,
oMSIZE
:
"MSIZE"
,
// 0x60 range - closures
oCREATE
:
"CREATE"
,
oCALL
:
"CALL"
,
oRETURN
:
"RETURN"
,
// 0x70 range - other
oLOG
:
"LOG"
,
oSUICIDE
:
"SUICIDE"
,
}
func
(
o
OpCode
)
String
()
string
{
return
opCodeToString
[
o
]
}
// Op codes for assembling
var
OpCodes
=
map
[
string
]
byte
{
// 0x0 range - arithmetic ops
"STOP"
:
0x00
,
"ADD"
:
0x01
,
"MUL"
:
0x02
,
"SUB"
:
0x03
,
"DIV"
:
0x04
,
"SDIV"
:
0x05
,
"MOD"
:
0x06
,
"SMOD"
:
0x07
,
"EXP"
:
0x08
,
"NEG"
:
0x09
,
"LT"
:
0x0a
,
"GT"
:
0x0b
,
"EQ"
:
0x0c
,
"NOT"
:
0x0d
,
// 0x10 range - bit ops
"AND"
:
0x10
,
"OR"
:
0x11
,
"XOR"
:
0x12
,
"BYTE"
:
0x13
,
// 0x20 range - crypto
"SHA3"
:
0x20
,
// 0x30 range - closure state
"ADDRESS"
:
0x30
,
"BALANCE"
:
0x31
,
"ORIGIN"
:
0x32
,
"CALLER"
:
0x33
,
"CALLVALUE"
:
0x34
,
"CALLDATA"
:
0x35
,
"CALLDATASIZE"
:
0x36
,
"GASPRICE"
:
0x38
,
// 0x40 range - block operations
"PREVHASH"
:
0x40
,
"COINBASE"
:
0x41
,
"TIMESTAMP"
:
0x42
,
"NUMBER"
:
0x43
,
"DIFFICULTY"
:
0x44
,
"GASLIMIT"
:
0x45
,
// 0x50 range - 'storage' and execution
"PUSH"
:
0x50
,
"PUSH20"
:
0x80
,
"POP"
:
0x51
,
"DUP"
:
0x52
,
"SWAP"
:
0x53
,
"MLOAD"
:
0x54
,
"MSTORE"
:
0x55
,
"MSTORE8"
:
0x56
,
"SLOAD"
:
0x57
,
"SSTORE"
:
0x58
,
"JUMP"
:
0x59
,
"JUMPI"
:
0x5a
,
"PC"
:
0x5b
,
"MSIZE"
:
0x5c
,
// 0x60 range - closures
"CREATE"
:
0x60
,
"CALL"
:
0x61
,
"RETURN"
:
0x62
,
// 0x70 range - other
"LOG"
:
0x70
,
"SUICIDE"
:
0x7f
,
}
func
IsOpCode
(
s
string
)
bool
{
for
key
,
_
:=
range
OpCodes
{
if
key
==
s
{
return
true
}
}
return
false
}
ethchain/vm.go
View file @
ca13e3b1
...
@@ -48,7 +48,19 @@ func NewVm(state *State, vars RuntimeVars) *Vm {
...
@@ -48,7 +48,19 @@ func NewVm(state *State, vars RuntimeVars) *Vm {
var
Pow256
=
ethutil
.
BigPow
(
2
,
256
)
var
Pow256
=
ethutil
.
BigPow
(
2
,
256
)
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
,
hook
DebugHook
)
[]
byte
{
var
isRequireError
=
false
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
,
hook
DebugHook
)
(
ret
[]
byte
,
err
error
)
{
// Recover from any require exception
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
&&
isRequireError
{
fmt
.
Println
(
r
)
ret
=
closure
.
Return
(
nil
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
}
}()
// If the amount of gas supplied is less equal to 0
// If the amount of gas supplied is less equal to 0
if
closure
.
Gas
.
Cmp
(
big
.
NewInt
(
0
))
<=
0
{
if
closure
.
Gas
.
Cmp
(
big
.
NewInt
(
0
))
<=
0
{
// TODO Do something
// TODO Do something
...
@@ -58,6 +70,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -58,6 +70,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
mem
:=
&
Memory
{}
mem
:=
&
Memory
{}
// New stack (should this be shared?)
// New stack (should this be shared?)
stack
:=
NewStack
()
stack
:=
NewStack
()
require
:=
func
(
m
int
)
{
if
stack
.
Len
()
-
1
>
m
{
isRequireError
=
true
panic
(
fmt
.
Sprintf
(
"stack = %d, req = %d"
,
stack
.
Len
(),
m
))
}
}
// Instruction pointer
// Instruction pointer
pc
:=
big
.
NewInt
(
0
)
pc
:=
big
.
NewInt
(
0
)
// Current step count
// Current step count
...
@@ -121,7 +140,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -121,7 +140,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
if
closure
.
Gas
.
Cmp
(
gas
)
<
0
{
if
closure
.
Gas
.
Cmp
(
gas
)
<
0
{
ethutil
.
Config
.
Log
.
Debugln
(
"Insufficient gas"
,
closure
.
Gas
,
gas
)
ethutil
.
Config
.
Log
.
Debugln
(
"Insufficient gas"
,
closure
.
Gas
,
gas
)
return
closure
.
Return
(
nil
)
return
closure
.
Return
(
nil
)
,
fmt
.
Errorf
(
"insufficient gas %v %v"
,
closure
.
Gas
,
gas
)
}
}
switch
op
{
switch
op
{
...
@@ -129,10 +148,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -129,10 +148,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
stack
.
Print
()
stack
.
Print
()
mem
.
Print
()
mem
.
Print
()
case
oSTOP
:
// Stop the closure
case
oSTOP
:
// Stop the closure
return
closure
.
Return
(
nil
)
return
closure
.
Return
(
nil
)
,
nil
// 0x20 range
// 0x20 range
case
oADD
:
case
oADD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Add
(
x
,
y
)
...
@@ -140,6 +160,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -140,6 +160,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSUB
:
case
oSUB
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Sub
(
x
,
y
)
...
@@ -147,6 +168,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -147,6 +168,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oMUL
:
case
oMUL
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mul
(
x
,
y
)
...
@@ -154,12 +176,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -154,12 +176,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oDIV
:
case
oDIV
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
// floor(x / y)
base
.
Div
(
x
,
y
)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSDIV
:
case
oSDIV
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// n > 2**255
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
if
x
.
Cmp
(
Pow256
)
>
0
{
...
@@ -176,10 +200,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -176,10 +200,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Push result on to the stack
// Push result on to the stack
stack
.
Push
(
z
)
stack
.
Push
(
z
)
case
oMOD
:
case
oMOD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
base
.
Mod
(
x
,
y
)
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSMOD
:
case
oSMOD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// n > 2**255
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
if
x
.
Cmp
(
Pow256
)
>
0
{
...
@@ -196,14 +222,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -196,14 +222,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Push result on to the stack
// Push result on to the stack
stack
.
Push
(
z
)
stack
.
Push
(
z
)
case
oEXP
:
case
oEXP
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
base
.
Exp
(
x
,
y
,
Pow256
)
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oNEG
:
case
oNEG
:
require
(
1
)
base
.
Sub
(
Pow256
,
stack
.
Pop
())
base
.
Sub
(
Pow256
,
stack
.
Pop
())
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oLT
:
case
oLT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x < y
// x < y
if
x
.
Cmp
(
y
)
<
0
{
if
x
.
Cmp
(
y
)
<
0
{
...
@@ -212,6 +241,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -212,6 +241,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oGT
:
case
oGT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x > y
// x > y
if
x
.
Cmp
(
y
)
>
0
{
if
x
.
Cmp
(
y
)
>
0
{
...
@@ -220,6 +250,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -220,6 +250,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oEQ
:
case
oEQ
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x == y
// x == y
if
x
.
Cmp
(
y
)
==
0
{
if
x
.
Cmp
(
y
)
==
0
{
...
@@ -228,6 +259,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -228,6 +259,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oNOT
:
case
oNOT
:
require
(
1
)
x
:=
stack
.
Pop
()
x
:=
stack
.
Pop
()
if
x
.
Cmp
(
ethutil
.
BigFalse
)
==
0
{
if
x
.
Cmp
(
ethutil
.
BigFalse
)
==
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -237,6 +269,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -237,6 +269,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// 0x10 range
// 0x10 range
case
oAND
:
case
oAND
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
&&
(
y
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
{
if
(
x
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
&&
(
y
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -245,6 +278,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -245,6 +278,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
}
}
case
oOR
:
case
oOR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
||
(
y
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
{
if
(
x
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
||
(
y
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -252,9 +286,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -252,9 +286,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oXOR
:
case
oXOR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
base
.
Xor
(
x
,
y
))
stack
.
Push
(
base
.
Xor
(
x
,
y
))
case
oBYTE
:
case
oBYTE
:
require
(
2
)
val
,
th
:=
stack
.
Popn
()
val
,
th
:=
stack
.
Popn
()
if
th
.
Cmp
(
big
.
NewInt
(
32
))
<
0
{
if
th
.
Cmp
(
big
.
NewInt
(
32
))
<
0
{
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
val
.
Bytes
())
-
1
)
-
th
.
Int64
()))
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
val
.
Bytes
())
-
1
)
-
th
.
Int64
()))
...
@@ -264,6 +300,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -264,6 +300,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// 0x20 range
// 0x20 range
case
oSHA3
:
case
oSHA3
:
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
size
,
offset
:=
stack
.
Popn
()
data
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
data
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
...
@@ -281,6 +318,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -281,6 +318,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// FIXME: Original value of the call, not the current value
// FIXME: Original value of the call, not the current value
stack
.
Push
(
closure
.
Value
)
stack
.
Push
(
closure
.
Value
)
case
oCALLDATA
:
case
oCALLDATA
:
require
(
1
)
offset
:=
stack
.
Pop
()
offset
:=
stack
.
Pop
()
mem
.
Set
(
offset
.
Int64
(),
int64
(
len
(
closure
.
Args
)),
closure
.
Args
)
mem
.
Set
(
offset
.
Int64
(),
int64
(
len
(
closure
.
Args
)),
closure
.
Args
)
case
oCALLDATASIZE
:
case
oCALLDATASIZE
:
...
@@ -324,34 +362,44 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -324,34 +362,44 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
pc
.
Add
(
pc
,
big
.
NewInt
(
19
))
pc
.
Add
(
pc
,
big
.
NewInt
(
19
))
step
++
step
++
case
oPOP
:
case
oPOP
:
require
(
1
)
stack
.
Pop
()
stack
.
Pop
()
case
oDUP
:
case
oDUP
:
require
(
1
)
stack
.
Push
(
stack
.
Peek
())
stack
.
Push
(
stack
.
Peek
())
case
oSWAP
:
case
oSWAP
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
y
)
stack
.
Push
(
y
)
stack
.
Push
(
x
)
stack
.
Push
(
x
)
case
oMLOAD
:
case
oMLOAD
:
require
(
1
)
offset
:=
stack
.
Pop
()
offset
:=
stack
.
Pop
()
stack
.
Push
(
ethutil
.
BigD
(
mem
.
Get
(
offset
.
Int64
(),
32
)))
stack
.
Push
(
ethutil
.
BigD
(
mem
.
Get
(
offset
.
Int64
(),
32
)))
case
oMSTORE
:
// Store the value at stack top-1 in to memory at location stack top
case
oMSTORE
:
// Store the value at stack top-1 in to memory at location stack top
require
(
2
)
// Pop value of the stack
// Pop value of the stack
val
,
mStart
:=
stack
.
Popn
()
val
,
mStart
:=
stack
.
Popn
()
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
case
oMSTORE8
:
case
oMSTORE8
:
require
(
2
)
val
,
mStart
:=
stack
.
Popn
()
val
,
mStart
:=
stack
.
Popn
()
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
case
oSLOAD
:
case
oSLOAD
:
require
(
1
)
loc
:=
stack
.
Pop
()
loc
:=
stack
.
Pop
()
val
:=
closure
.
GetMem
(
loc
)
val
:=
closure
.
GetMem
(
loc
)
stack
.
Push
(
val
.
BigInt
())
stack
.
Push
(
val
.
BigInt
())
case
oSSTORE
:
case
oSSTORE
:
require
(
2
)
val
,
loc
:=
stack
.
Popn
()
val
,
loc
:=
stack
.
Popn
()
closure
.
SetMem
(
loc
,
ethutil
.
NewValue
(
val
))
closure
.
SetMem
(
loc
,
ethutil
.
NewValue
(
val
))
case
oJUMP
:
case
oJUMP
:
require
(
1
)
pc
=
stack
.
Pop
()
pc
=
stack
.
Pop
()
case
oJUMPI
:
case
oJUMPI
:
require
(
2
)
cond
,
pos
:=
stack
.
Popn
()
cond
,
pos
:=
stack
.
Popn
()
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
==
0
{
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
==
0
{
pc
=
pos
pc
=
pos
...
@@ -361,7 +409,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -361,7 +409,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
case
oMSIZE
:
case
oMSIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
stack
.
Push
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
// 0x60 range
// 0x60 range
case
oCREATE
:
case
oCALL
:
case
oCALL
:
require
(
8
)
// Closure addr
// Closure addr
addr
:=
stack
.
Pop
()
addr
:=
stack
.
Pop
()
// Pop gas and value of the stack.
// Pop gas and value of the stack.
...
@@ -377,14 +427,20 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -377,14 +427,20 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// Create a new callable closure
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
contract
.
script
,
vm
.
state
,
gas
,
value
)
closure
:=
NewClosure
(
closure
,
contract
,
contract
.
script
,
vm
.
state
,
gas
,
value
)
// Executer the closure and get the return value (if any)
// Executer the closure and get the return value (if any)
ret
:=
closure
.
Call
(
vm
,
args
,
hook
)
ret
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
else
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
case
oRETURN
:
case
oRETURN
:
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
size
,
offset
:=
stack
.
Popn
()
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
return
closure
.
Return
(
ret
)
return
closure
.
Return
(
ret
)
,
nil
case
oSUICIDE
:
case
oSUICIDE
:
/*
/*
recAddr := stack.Pop().Bytes()
recAddr := stack.Pop().Bytes()
...
@@ -405,7 +461,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -405,7 +461,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
default
:
default
:
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid opcode %x
\n
"
,
op
)
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid opcode %x
\n
"
,
op
)
return
closure
.
Return
(
nil
)
return
closure
.
Return
(
nil
)
,
fmt
.
Errorf
(
"Invalid opcode %x"
,
op
)
}
}
pc
.
Add
(
pc
,
ethutil
.
Big1
)
pc
.
Add
(
pc
,
ethutil
.
Big1
)
...
@@ -415,55 +471,3 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
...
@@ -415,55 +471,3 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
}
}
}
}
}
}
func
Disassemble
(
script
[]
byte
)
(
asm
[]
string
)
{
pc
:=
new
(
big
.
Int
)
for
{
if
pc
.
Cmp
(
big
.
NewInt
(
int64
(
len
(
script
))))
>=
0
{
return
}
// Get the memory location of pc
val
:=
script
[
pc
.
Int64
()]
// Get the opcode (it must be an opcode!)
op
:=
OpCode
(
val
)
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"%v"
,
op
))
switch
op
{
case
oPUSH
:
// Push PC+1 on to the stack
pc
.
Add
(
pc
,
ethutil
.
Big1
)
data
:=
script
[
pc
.
Int64
()
:
pc
.
Int64
()
+
32
]
val
:=
ethutil
.
BigD
(
data
)
var
b
[]
byte
if
val
.
Int64
()
==
0
{
b
=
[]
byte
{
0
}
}
else
{
b
=
val
.
Bytes
()
}
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"0x%x"
,
b
))
pc
.
Add
(
pc
,
big
.
NewInt
(
31
))
case
oPUSH20
:
pc
.
Add
(
pc
,
ethutil
.
Big1
)
data
:=
script
[
pc
.
Int64
()
:
pc
.
Int64
()
+
20
]
val
:=
ethutil
.
BigD
(
data
)
var
b
[]
byte
if
val
.
Int64
()
==
0
{
b
=
[]
byte
{
0
}
}
else
{
b
=
val
.
Bytes
()
}
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"0x%x"
,
b
))
pc
.
Add
(
pc
,
big
.
NewInt
(
19
))
}
pc
.
Add
(
pc
,
ethutil
.
Big1
)
}
return
}
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