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
fa1db8d2
Commit
fa1db8d2
authored
Mar 21, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented closure arguments
parent
9cf8ce9e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
225 additions
and
22 deletions
+225
-22
stack.go
ethchain/stack.go
+23
-5
vm.go
ethchain/vm.go
+175
-9
vm_test.go
ethchain/vm_test.go
+22
-7
parsing.go
ethutil/parsing.go
+5
-1
No files found.
ethchain/stack.go
View file @
fa1db8d2
...
@@ -68,12 +68,16 @@ const (
...
@@ -68,12 +68,16 @@ const (
oJUMP
=
0x59
oJUMP
=
0x59
oJUMPI
=
0x5a
oJUMPI
=
0x5a
oPC
=
0x5b
oPC
=
0x5b
oM
EMSIZE
=
0x5c
oM
SIZE
=
0x5c
// 0x60 range - closures
// 0x60 range - closures
oCREATE
=
0x60
oCREATE
=
0x60
oCALL
=
0x61
oCALL
=
0x61
oRETURN
=
0x62
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
// Since the opcodes aren't all in order we can't use a regular slice
...
@@ -136,12 +140,16 @@ var opCodeToString = map[OpCode]string{
...
@@ -136,12 +140,16 @@ var opCodeToString = map[OpCode]string{
oJUMP
:
"JUMP"
,
oJUMP
:
"JUMP"
,
oJUMPI
:
"JUMPI"
,
oJUMPI
:
"JUMPI"
,
oPC
:
"PC"
,
oPC
:
"PC"
,
oM
EMSIZE
:
"ME
MSIZE"
,
oM
SIZE
:
"
MSIZE"
,
// 0x60 range - closures
// 0x60 range - closures
oCREATE
:
"CREATE"
,
oCREATE
:
"CREATE"
,
oCALL
:
"CALL"
,
oCALL
:
"CALL"
,
oRETURN
:
"RETURN"
,
oRETURN
:
"RETURN"
,
// 0x70 range - other
oLOG
:
"LOG"
,
oSUICIDE
:
"SUICIDE"
,
}
}
func
(
o
OpCode
)
String
()
string
{
func
(
o
OpCode
)
String
()
string
{
...
@@ -215,20 +223,30 @@ type Memory struct {
...
@@ -215,20 +223,30 @@ type Memory struct {
func
(
m
*
Memory
)
Set
(
offset
,
size
int64
,
value
[]
byte
)
{
func
(
m
*
Memory
)
Set
(
offset
,
size
int64
,
value
[]
byte
)
{
totSize
:=
offset
+
size
totSize
:=
offset
+
size
lenSize
:=
int64
(
len
(
m
.
store
))
lenSize
:=
int64
(
len
(
m
.
store
)
-
1
)
if
totSize
>
lenSize
{
if
totSize
>
lenSize
{
// Calculate the diff between the sizes
// Calculate the diff between the sizes
diff
:=
totSize
-
lenSize
diff
:=
totSize
-
lenSize
if
diff
>
0
{
if
diff
>
0
{
// Create a new empty slice and append it
// Create a new empty slice and append it
newSlice
:=
make
([]
byte
,
diff
+
1
)
newSlice
:=
make
([]
byte
,
diff
-
1
)
// Resize slice
// Resize slice
m
.
store
=
append
(
m
.
store
,
newSlice
...
)
m
.
store
=
append
(
m
.
store
,
newSlice
...
)
}
}
}
}
copy
(
m
.
store
[
offset
:
offset
+
size
+
1
],
value
)
copy
(
m
.
store
[
offset
:
offset
+
size
],
value
)
}
}
func
(
m
*
Memory
)
Get
(
offset
,
size
int64
)
[]
byte
{
func
(
m
*
Memory
)
Get
(
offset
,
size
int64
)
[]
byte
{
return
m
.
store
[
offset
:
offset
+
size
]
return
m
.
store
[
offset
:
offset
+
size
]
}
}
func
(
m
*
Memory
)
Print
()
{
fmt
.
Println
(
"### MEM ###"
)
if
len
(
m
.
store
)
>
0
{
fmt
.
Println
(
m
.
store
)
}
else
{
fmt
.
Println
(
"-- empty --"
)
}
fmt
.
Println
(
"###########"
)
}
ethchain/vm.go
View file @
fa1db8d2
...
@@ -2,7 +2,7 @@ package ethchain
...
@@ -2,7 +2,7 @@ package ethchain
import
(
import
(
_
"bytes"
_
"bytes"
"fmt"
_
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
_
"github.com/obscuren/secp256k1-go"
_
"github.com/obscuren/secp256k1-go"
"log"
"log"
...
@@ -36,6 +36,8 @@ func NewVm(state *State, vars RuntimeVars) *Vm {
...
@@ -36,6 +36,8 @@ func NewVm(state *State, vars RuntimeVars) *Vm {
return
&
Vm
{
vars
:
vars
,
state
:
state
}
return
&
Vm
{
vars
:
vars
,
state
:
state
}
}
}
var
Pow256
=
ethutil
.
BigPow
(
2
,
256
)
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
)
[]
byte
{
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
)
[]
byte
{
// If the amount of gas supplied is less equal to 0
// If the amount of gas supplied is less equal to 0
if
closure
.
GetGas
()
.
Cmp
(
big
.
NewInt
(
0
))
<=
0
{
if
closure
.
GetGas
()
.
Cmp
(
big
.
NewInt
(
0
))
<=
0
{
...
@@ -48,9 +50,10 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
...
@@ -48,9 +50,10 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
stack
:=
NewStack
()
stack
:=
NewStack
()
// Instruction pointer
// Instruction pointer
pc
:=
int64
(
0
)
pc
:=
int64
(
0
)
// Current address
// Current step count
//addr := vars.address
step
:=
0
step
:=
0
// The base for all big integer arithmetic
base
:=
new
(
big
.
Int
)
if
ethutil
.
Config
.
Debug
{
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
...
@@ -75,27 +78,171 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
...
@@ -75,27 +78,171 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
}
}
switch
op
{
switch
op
{
case
oLOG
:
stack
.
Print
()
mem
.
Print
()
case
oSTOP
:
// Stop the closure
case
oSTOP
:
// Stop the closure
return
closure
.
Return
(
nil
)
return
closure
.
Return
(
nil
)
// 0x20 range
case
oADD
:
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
oSUB
:
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
oMUL
:
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
oDIV
:
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
oSDIV
:
x
,
y
:=
stack
.
Popn
()
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
z
:=
new
(
big
.
Int
)
z
.
Div
(
x
,
y
)
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
stack
.
Push
(
z
)
case
oMOD
:
x
,
y
:=
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
stack
.
Push
(
base
)
case
oSMOD
:
x
,
y
:=
stack
.
Popn
()
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
z
:=
new
(
big
.
Int
)
z
.
Mod
(
x
,
y
)
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
stack
.
Push
(
z
)
case
oEXP
:
x
,
y
:=
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
stack
.
Push
(
base
)
case
oNEG
:
base
.
Sub
(
Pow256
,
stack
.
Pop
())
stack
.
Push
(
base
)
case
oLT
:
x
,
y
:=
stack
.
Popn
()
// x < y
if
x
.
Cmp
(
y
)
<
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oGT
:
x
,
y
:=
stack
.
Popn
()
// x > y
if
x
.
Cmp
(
y
)
>
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oNOT
:
x
,
y
:=
stack
.
Popn
()
// x != y
if
x
.
Cmp
(
y
)
!=
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
// 0x10 range
case
oAND
:
case
oOR
:
case
oXOR
:
case
oBYTE
:
// 0x20 range
case
oSHA3
:
// 0x30 range
case
oADDRESS
:
case
oBALANCE
:
case
oORIGIN
:
case
oCALLER
:
case
oCALLVALUE
:
case
oCALLDATA
:
offset
:=
stack
.
Pop
()
mem
.
Set
(
offset
.
Int64
(),
int64
(
len
(
closure
.
Args
)),
closure
.
Args
)
case
oCALLDATASIZE
:
case
oRETURNDATASIZE
:
case
oTXGASPRICE
:
// 0x40 range
case
oPREVHASH
:
case
oPREVNONCE
:
case
oCOINBASE
:
case
oTIMESTAMP
:
case
oNUMBER
:
case
oDIFFICULTY
:
case
oGASLIMIT
:
// 0x50 range
case
oPUSH
:
// Push PC+1 on to the stack
case
oPUSH
:
// Push PC+1 on to the stack
pc
++
pc
++
val
:=
closure
.
GetMem
(
pc
)
.
BigInt
()
val
:=
closure
.
GetMem
(
pc
)
.
BigInt
()
stack
.
Push
(
val
)
stack
.
Push
(
val
)
case
oPOP
:
case
oDUP
:
case
oSWAP
:
case
oMLOAD
:
offset
:=
stack
.
Pop
()
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
// 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
oSLOAD
:
case
oSSTORE
:
case
oJUMP
:
case
oJUMPI
:
case
oPC
:
case
oMSIZE
:
case
oCALLDATA
:
// 0x60 range
offset
:=
stack
.
Pop
()
mem
.
Set
(
offset
.
Int64
(),
int64
(
len
(
closure
.
Args
)),
closure
.
Args
)
case
oCALL
:
case
oCALL
:
// Pop return size and offset
// Pop return size and offset
retSize
,
retOffset
:=
stack
.
Popn
()
retSize
,
retOffset
:=
stack
.
Popn
()
// Pop input size and offset
// Pop input size and offset
inSize
,
inOffset
:=
stack
.
Popn
()
inSize
,
inOffset
:=
stack
.
Popn
()
//
TODO remove me.
//
Get the arguments from the memory
fmt
.
Sprintln
(
inSize
,
inOffset
)
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
()
)
// Pop gas and value of the stack.
// Pop gas and value of the stack.
gas
,
value
:=
stack
.
Popn
()
gas
,
value
:=
stack
.
Popn
()
// Closure addr
// Closure addr
...
@@ -105,7 +252,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
...
@@ -105,7 +252,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
// Create a new callable closure
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
vm
.
state
,
gas
,
value
)
closure
:=
NewClosure
(
closure
,
contract
,
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
,
nil
)
ret
:=
closure
.
Call
(
vm
,
args
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
case
oRETURN
:
case
oRETURN
:
...
@@ -113,6 +260,25 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
...
@@ -113,6 +260,25 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
return
closure
.
Return
(
ret
)
return
closure
.
Return
(
ret
)
case
oSUICIDE
:
/*
recAddr := stack.Pop().Bytes()
// Purge all memory
deletedMemory := contract.state.Purge()
// Add refunds to the pop'ed address
refund := new(big.Int).Mul(StoreFee, big.NewInt(int64(deletedMemory)))
account := state.GetAccount(recAddr)
account.Amount.Add(account.Amount, refund)
// Update the refunding address
state.UpdateAccount(recAddr, account)
// Delete the contract
state.trie.Update(string(addr), "")
ethutil.Config.Log.Debugf("(%d) => %x\n", deletedMemory, recAddr)
break out
*/
default
:
ethutil
.
Config
.
Log
.
Debugln
(
"Invalid opcode"
,
op
)
}
}
pc
++
pc
++
...
...
ethchain/vm_test.go
View file @
fa1db8d2
package
ethchain
package
ethchain
import
(
import
(
"bytes"
"fmt"
"fmt"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
...
@@ -119,11 +120,13 @@ func TestRun3(t *testing.T) {
...
@@ -119,11 +120,13 @@ func TestRun3(t *testing.T) {
"PUSH"
,
"300"
,
"PUSH"
,
"300"
,
"PUSH"
,
"0"
,
"PUSH"
,
"0"
,
"MSTORE"
,
"MSTORE"
,
"PUSH"
,
"300"
,
"PUSH"
,
"31"
,
"PUSH"
,
"32"
,
"MSTORE"
,
"CALLDATA"
,
"PUSH"
,
"62"
,
"PUSH"
,
"64"
,
"PUSH"
,
"0"
,
"PUSH"
,
"0"
,
"LOG"
,
"RETURN"
,
"RETURN"
,
})
})
tx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
script
)
tx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
script
)
...
@@ -133,14 +136,21 @@ func TestRun3(t *testing.T) {
...
@@ -133,14 +136,21 @@ func TestRun3(t *testing.T) {
state
.
UpdateContract
(
contract
)
state
.
UpdateContract
(
contract
)
callerScript
:=
Compile
([]
string
{
callerScript
:=
Compile
([]
string
{
"PUSH"
,
"62"
,
// ret size
"PUSH"
,
"1337"
,
// Argument
"PUSH"
,
"65"
,
// argument mem offset
"MSTORE"
,
"PUSH"
,
"64"
,
// ret size
"PUSH"
,
"0"
,
// ret offset
"PUSH"
,
"0"
,
// ret offset
"PUSH"
,
"32"
,
// arg size
"PUSH"
,
"32"
,
// arg size
"PUSH"
,
"6
3
"
,
// arg offset
"PUSH"
,
"6
5
"
,
// arg offset
"PUSH"
,
"1000"
,
/// Gas
"PUSH"
,
"1000"
,
/// Gas
"PUSH"
,
"0"
,
/// value
"PUSH"
,
"0"
,
/// value
"PUSH"
,
string
(
addr
),
// Sender
"PUSH"
,
string
(
addr
),
// Sender
"CALL"
,
"CALL"
,
"PUSH"
,
"64"
,
"PUSH"
,
"0"
,
"RETURN"
,
})
})
callerTx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
callerScript
)
callerTx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
callerScript
)
...
@@ -158,5 +168,10 @@ func TestRun3(t *testing.T) {
...
@@ -158,5 +168,10 @@ func TestRun3(t *testing.T) {
// XXX Tx data? Could be just an argument to the closure instead
// XXX Tx data? Could be just an argument to the closure instead
txData
:
nil
,
txData
:
nil
,
})
})
callerClosure
.
Call
(
vm
,
nil
)
ret
:=
callerClosure
.
Call
(
vm
,
nil
)
exp
:=
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
44
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
5
,
57
}
if
bytes
.
Compare
(
ret
,
exp
)
!=
0
{
t
.
Errorf
(
"expected return value to be %v, got %v"
,
exp
,
ret
)
}
}
}
ethutil/parsing.go
View file @
fa1db8d2
...
@@ -65,12 +65,16 @@ var OpCodes = map[string]byte{
...
@@ -65,12 +65,16 @@ var OpCodes = map[string]byte{
"JUMP"
:
0x59
,
"JUMP"
:
0x59
,
"JUMPI"
:
0x5a
,
"JUMPI"
:
0x5a
,
"PC"
:
0x5b
,
"PC"
:
0x5b
,
"M
EMSIZE"
:
0x5c
,
"M
SIZE"
:
0x5c
,
// 0x60 range - closures
// 0x60 range - closures
"CREATE"
:
0x60
,
"CREATE"
:
0x60
,
"CALL"
:
0x61
,
"CALL"
:
0x61
,
"RETURN"
:
0x62
,
"RETURN"
:
0x62
,
// 0x70 range - other
"LOG"
:
0x70
,
"SUICIDE"
:
0x7f
,
}
}
func
IsOpCode
(
s
string
)
bool
{
func
IsOpCode
(
s
string
)
bool
{
...
...
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