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
69302609
Commit
69302609
authored
Apr 19, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated VM
parent
a96c8c8a
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
89 additions
and
36 deletions
+89
-36
closure.go
ethchain/closure.go
+4
-6
state_object.go
ethchain/state_object.go
+20
-2
vm.go
ethchain/vm.go
+36
-16
vm_test.go
ethchain/vm_test.go
+29
-12
No files found.
ethchain/closure.go
View file @
69302609
...
@@ -8,7 +8,7 @@ import (
...
@@ -8,7 +8,7 @@ import (
)
)
type
Callee
interface
{
type
Callee
interface
{
ReturnGas
(
*
big
.
Int
,
*
State
)
ReturnGas
(
*
big
.
Int
,
*
big
.
Int
,
*
State
)
Address
()
[]
byte
Address
()
[]
byte
}
}
...
@@ -83,18 +83,16 @@ func (c *Closure) Return(ret []byte) []byte {
...
@@ -83,18 +83,16 @@ func (c *Closure) Return(ret []byte) []byte {
// If no callee is present return it to
// If no callee is present return it to
// the origin (i.e. contract or tx)
// the origin (i.e. contract or tx)
if
c
.
callee
!=
nil
{
if
c
.
callee
!=
nil
{
c
.
callee
.
ReturnGas
(
c
.
Gas
,
c
.
State
)
c
.
callee
.
ReturnGas
(
c
.
Gas
,
c
.
Price
,
c
.
State
)
}
else
{
}
else
{
c
.
object
.
ReturnGas
(
c
.
Gas
,
c
.
State
)
c
.
object
.
ReturnGas
(
c
.
Gas
,
c
.
Price
,
c
.
State
)
// TODO incase it's a POST contract we gotta serialise the contract again.
// But it's not yet defined
}
}
return
ret
return
ret
}
}
// Implement the Callee interface
// Implement the Callee interface
func
(
c
*
Closure
)
ReturnGas
(
gas
*
big
.
Int
,
state
*
State
)
{
func
(
c
*
Closure
)
ReturnGas
(
gas
,
price
*
big
.
Int
,
state
*
State
)
{
// Return the gas to the closure
// Return the gas to the closure
c
.
Gas
.
Add
(
c
.
Gas
,
gas
)
c
.
Gas
.
Add
(
c
.
Gas
,
gas
)
}
}
...
...
ethchain/state_object.go
View file @
69302609
package
ethchain
package
ethchain
import
(
import
(
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"math/big"
)
)
...
@@ -70,8 +71,9 @@ func (c *StateObject) SetMem(num *big.Int, val *ethutil.Value) {
...
@@ -70,8 +71,9 @@ func (c *StateObject) SetMem(num *big.Int, val *ethutil.Value) {
}
}
// Return the gas back to the origin. Used by the Virtual machine or Closures
// Return the gas back to the origin. Used by the Virtual machine or Closures
func
(
c
*
StateObject
)
ReturnGas
(
val
*
big
.
Int
,
state
*
State
)
{
func
(
c
*
StateObject
)
ReturnGas
(
gas
,
price
*
big
.
Int
,
state
*
State
)
{
c
.
AddAmount
(
val
)
remainder
:=
new
(
big
.
Int
)
.
Mul
(
gas
,
price
)
c
.
AddAmount
(
remainder
)
}
}
func
(
c
*
StateObject
)
AddAmount
(
amount
*
big
.
Int
)
{
func
(
c
*
StateObject
)
AddAmount
(
amount
*
big
.
Int
)
{
...
@@ -82,18 +84,33 @@ func (c *StateObject) SubAmount(amount *big.Int) {
...
@@ -82,18 +84,33 @@ func (c *StateObject) SubAmount(amount *big.Int) {
c
.
Amount
.
Sub
(
c
.
Amount
,
amount
)
c
.
Amount
.
Sub
(
c
.
Amount
,
amount
)
}
}
func
(
c
*
StateObject
)
ConvertGas
(
gas
,
price
*
big
.
Int
)
error
{
total
:=
new
(
big
.
Int
)
.
Mul
(
gas
,
price
)
if
total
.
Cmp
(
c
.
Amount
)
>
0
{
return
fmt
.
Errorf
(
"insufficient amount: %v, %v"
,
c
.
Amount
,
total
)
}
c
.
SubAmount
(
total
)
return
nil
}
// Returns the address of the contract/account
func
(
c
*
StateObject
)
Address
()
[]
byte
{
func
(
c
*
StateObject
)
Address
()
[]
byte
{
return
c
.
address
return
c
.
address
}
}
// Returns the main script body
func
(
c
*
StateObject
)
Script
()
[]
byte
{
func
(
c
*
StateObject
)
Script
()
[]
byte
{
return
c
.
script
return
c
.
script
}
}
// Returns the initialization script
func
(
c
*
StateObject
)
Init
()
[]
byte
{
func
(
c
*
StateObject
)
Init
()
[]
byte
{
return
c
.
initScript
return
c
.
initScript
}
}
// State object encoding methods
func
(
c
*
StateObject
)
RlpEncode
()
[]
byte
{
func
(
c
*
StateObject
)
RlpEncode
()
[]
byte
{
var
root
interface
{}
var
root
interface
{}
if
c
.
state
!=
nil
{
if
c
.
state
!=
nil
{
...
@@ -113,6 +130,7 @@ func (c *StateObject) RlpDecode(data []byte) {
...
@@ -113,6 +130,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c
.
script
=
decoder
.
Get
(
3
)
.
Bytes
()
c
.
script
=
decoder
.
Get
(
3
)
.
Bytes
()
}
}
// Converts an transaction in to a state object
func
MakeContract
(
tx
*
Transaction
,
state
*
State
)
*
StateObject
{
func
MakeContract
(
tx
*
Transaction
,
state
*
State
)
*
StateObject
{
// Create contract if there's no recipient
// Create contract if there's no recipient
if
tx
.
IsContract
()
{
if
tx
.
IsContract
()
{
...
...
ethchain/vm.go
View file @
69302609
...
@@ -102,10 +102,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -102,10 +102,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
}
*/
*/
// TODO Get each instruction cost properly
gas
:=
new
(
big
.
Int
)
gas
:=
new
(
big
.
Int
)
useGas
:=
func
(
amount
*
big
.
Int
)
{
useGas
:=
func
(
amount
*
big
.
Int
)
{
gas
.
Add
(
gas
,
new
(
big
.
Int
)
.
Mul
(
amount
,
closure
.
Price
)
)
gas
.
Add
(
gas
,
amount
)
}
}
switch
op
{
switch
op
{
...
@@ -142,6 +141,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -142,6 +141,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
return
closure
.
Return
(
nil
),
fmt
.
Errorf
(
"insufficient gas %v %v"
,
closure
.
Gas
,
gas
)
return
closure
.
Return
(
nil
),
fmt
.
Errorf
(
"insufficient gas %v %v"
,
closure
.
Gas
,
gas
)
}
}
// Sub the amount of gas from the remaining
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
switch
op
{
switch
op
{
...
@@ -157,7 +158,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -157,7 +158,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSUB
:
case
oSUB
:
...
@@ -165,7 +165,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -165,7 +165,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oMUL
:
case
oMUL
:
...
@@ -173,7 +172,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -173,7 +172,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oDIV
:
case
oDIV
:
...
@@ -325,7 +323,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -325,7 +323,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
oCALLDATASIZE
:
case
oCALLDATASIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Args
))))
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Args
))))
case
oGASPRICE
:
case
oGASPRICE
:
// TODO
stack
.
Push
(
closure
.
Price
)
// 0x40 range
// 0x40 range
case
oPREVHASH
:
case
oPREVHASH
:
...
@@ -340,6 +338,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -340,6 +338,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack
.
Push
(
vm
.
vars
.
Diff
)
stack
.
Push
(
vm
.
vars
.
Diff
)
case
oGASLIMIT
:
case
oGASLIMIT
:
// TODO
// TODO
stack
.
Push
(
big
.
NewInt
(
0
))
// 0x50 range
// 0x50 range
case
oPUSH
:
// Push PC+1 on to the stack
case
oPUSH
:
// Push PC+1 on to the stack
...
@@ -399,11 +398,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -399,11 +398,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
oJUMP
:
case
oJUMP
:
require
(
1
)
require
(
1
)
pc
=
stack
.
Pop
()
pc
=
stack
.
Pop
()
// Reduce pc by one because of the increment that's at the end of this for loop
pc
.
Sub
(
pc
,
ethutil
.
Big1
)
case
oJUMPI
:
case
oJUMPI
:
require
(
2
)
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
pc
.
Sub
(
pc
,
ethutil
.
Big1
)
}
}
case
oPC
:
case
oPC
:
stack
.
Push
(
pc
)
stack
.
Push
(
pc
)
...
@@ -421,10 +423,24 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -421,10 +423,24 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
inSize
,
inOffset
:=
stack
.
Popn
()
inSize
,
inOffset
:=
stack
.
Popn
()
// Pop return size and offset
// Pop return size and offset
retSize
,
retOffset
:=
stack
.
Popn
()
retSize
,
retOffset
:=
stack
.
Popn
()
// Make sure there's enough gas
if
closure
.
Gas
.
Cmp
(
gas
)
<
0
{
stack
.
Push
(
ethutil
.
BigFalse
)
break
}
// Get the arguments from the memory
// Get the arguments from the memory
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
// Fetch the contract which will serve as the closure body
// Fetch the contract which will serve as the closure body
contract
:=
vm
.
state
.
GetContract
(
addr
.
Bytes
())
contract
:=
vm
.
state
.
GetContract
(
addr
.
Bytes
())
if
contract
!=
nil
{
// Prepay for the gas
// If gas is set to 0 use all remaining gas for the next call
if
gas
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
gas
=
closure
.
Gas
}
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
// Create a new callable closure
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
contract
.
script
,
vm
.
state
,
gas
,
closure
.
Price
,
value
)
closure
:=
NewClosure
(
closure
,
contract
,
contract
.
script
,
vm
.
state
,
gas
,
closure
.
Price
,
value
)
// Executer the closure and get the return value (if any)
// Executer the closure and get the return value (if any)
...
@@ -436,6 +452,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -436,6 +452,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
}
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
}
else
{
ethutil
.
Config
.
Log
.
Debugf
(
"Contract %x not found
\n
"
,
addr
.
Bytes
())
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oRETURN
:
case
oRETURN
:
require
(
2
)
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
size
,
offset
:=
stack
.
Popn
()
...
...
ethchain/vm_test.go
View file @
69302609
...
@@ -86,9 +86,9 @@ func TestRun4(t *testing.T) {
...
@@ -86,9 +86,9 @@ func TestRun4(t *testing.T) {
int32 a = 10
int32 a = 10
int32 b = 20
int32 b = 20
if a > b {
if a > b {
int32 c = this.
c
aller()
int32 c = this.
C
aller()
}
}
e
xit()
E
xit()
`
),
false
)
`
),
false
)
script
:=
ethutil
.
Assemble
(
asm
...
)
script
:=
ethutil
.
Assemble
(
asm
...
)
tx
:=
NewContractCreationTx
(
ethutil
.
Big
(
"0"
),
ethutil
.
Big
(
"1000"
),
script
,
nil
)
tx
:=
NewContractCreationTx
(
ethutil
.
Big
(
"0"
),
ethutil
.
Big
(
"1000"
),
script
,
nil
)
...
@@ -103,8 +103,9 @@ func TestRun4(t *testing.T) {
...
@@ -103,8 +103,9 @@ func TestRun4(t *testing.T) {
store[1000] = 10^20
store[1000] = 10^20
}
}
store[1001] = this.value() * 20
store[this.origin()] = store[this.origin()] + 1000
store[1001] = this.Value() * 20
store[this.Origin()] = store[this.Origin()] + 1000
if store[1001] > 20 {
if store[1001] > 20 {
store[1001] = 10^50
store[1001] = 10^50
...
@@ -112,8 +113,18 @@ func TestRun4(t *testing.T) {
...
@@ -112,8 +113,18 @@ func TestRun4(t *testing.T) {
int8 ret = 0
int8 ret = 0
int8 arg = 10
int8 arg = 10
store[1002] = "a46df28529eb8aa8b8c025b0b413c5f4b688352f"
Call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
call(store[1002], 0, 100000000, arg, ret)
big t
for int8 i = 0; i < 10; i++ {
t = i
}
if 10 > 20 {
int8 shouldnt = 2
} else {
int8 should = 1
}
`
),
false
)
`
),
false
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
...
@@ -125,10 +136,17 @@ func TestRun4(t *testing.T) {
...
@@ -125,10 +136,17 @@ func TestRun4(t *testing.T) {
callerTx
:=
NewContractCreationTx
(
ethutil
.
Big
(
"0"
),
ethutil
.
Big
(
"1000"
),
callerScript
,
nil
)
callerTx
:=
NewContractCreationTx
(
ethutil
.
Big
(
"0"
),
ethutil
.
Big
(
"1000"
),
callerScript
,
nil
)
// Contract addr as test address
// Contract addr as test address
gas
:=
big
.
NewInt
(
1000
)
gasPrice
:=
big
.
NewInt
(
10
)
account
:=
NewAccount
(
ContractAddr
,
big
.
NewInt
(
10000000
))
account
:=
NewAccount
(
ContractAddr
,
big
.
NewInt
(
10000000
))
fmt
.
Println
(
acc
ount
)
fmt
.
Println
(
"account.Amount ="
,
account
.
Am
ount
)
c
:=
MakeContract
(
callerTx
,
state
)
c
:=
MakeContract
(
callerTx
,
state
)
callerClosure
:=
NewClosure
(
account
,
c
,
c
.
script
,
state
,
big
.
NewInt
(
1000000000
),
big
.
NewInt
(
10
),
big
.
NewInt
(
0
))
e
:=
account
.
ConvertGas
(
gas
,
gasPrice
)
if
e
!=
nil
{
fmt
.
Println
(
err
)
}
fmt
.
Println
(
"account.Amount ="
,
account
.
Amount
)
callerClosure
:=
NewClosure
(
account
,
c
,
c
.
script
,
state
,
gas
,
gasPrice
,
big
.
NewInt
(
0
))
vm
:=
NewVm
(
state
,
RuntimeVars
{
vm
:=
NewVm
(
state
,
RuntimeVars
{
Origin
:
account
.
Address
(),
Origin
:
account
.
Address
(),
...
@@ -138,11 +156,11 @@ func TestRun4(t *testing.T) {
...
@@ -138,11 +156,11 @@ func TestRun4(t *testing.T) {
Time
:
1
,
Time
:
1
,
Diff
:
big
.
NewInt
(
256
),
Diff
:
big
.
NewInt
(
256
),
})
})
_
,
e
:
=
callerClosure
.
Call
(
vm
,
nil
,
nil
)
_
,
e
=
callerClosure
.
Call
(
vm
,
nil
,
nil
)
if
e
!=
nil
{
if
e
!=
nil
{
fmt
.
Println
(
"error"
,
e
)
fmt
.
Println
(
"error"
,
e
)
}
}
fmt
.
Println
(
acc
ount
)
fmt
.
Println
(
"account.Amount ="
,
account
.
Am
ount
)
}
}
func
TestRun5
(
t
*
testing
.
T
)
{
func
TestRun5
(
t
*
testing
.
T
)
{
...
@@ -156,6 +174,5 @@ func TestRun5(t *testing.T) {
...
@@ -156,6 +174,5 @@ func TestRun5(t *testing.T) {
}
}
exit()
exit()
`
),
false
)
`
),
false
)
script
:=
ethutil
.
Assemble
(
asm
...
)
ethutil
.
Assemble
(
asm
...
)
fmt
.
Println
(
Disassemble
(
script
))
}
}
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