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
198cc693
Commit
198cc693
authored
Dec 18, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Gas corrections and vm fixes
parent
5ad473d7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
116 additions
and
83 deletions
+116
-83
block_manager.go
core/block_manager.go
+1
-1
state_transition.go
core/state_transition.go
+37
-36
transaction.go
core/types/transaction.go
+0
-9
state.go
state/state.go
+10
-20
vm.go
tests/helper/vm.go
+32
-5
gh_test.go
tests/vm/gh_test.go
+25
-1
common.go
vm/common.go
+1
-1
vm_debug.go
vm/vm_debug.go
+10
-10
No files found.
core/block_manager.go
View file @
198cc693
...
...
@@ -115,7 +115,7 @@ done:
cb
:=
state
.
GetStateObject
(
coinbase
.
Address
())
st
:=
NewStateTransition
(
cb
,
tx
,
state
,
block
)
err
=
st
.
TransitionState
()
_
,
err
=
st
.
TransitionState
()
if
err
!=
nil
{
switch
{
case
IsNonceErr
(
err
)
:
...
...
core/state_transition.go
View file @
198cc693
...
...
@@ -31,6 +31,7 @@ type StateTransition struct {
coinbase
,
receiver
[]
byte
msg
Message
gas
,
gasPrice
*
big
.
Int
initialGas
*
big
.
Int
value
*
big
.
Int
data
[]
byte
state
*
state
.
StateDB
...
...
@@ -47,7 +48,6 @@ type Message interface {
From
()
[]
byte
To
()
[]
byte
GasValue
()
*
big
.
Int
GasPrice
()
*
big
.
Int
Gas
()
*
big
.
Int
Value
()
*
big
.
Int
...
...
@@ -65,8 +65,12 @@ func MessageCreatesContract(msg Message) bool {
return
len
(
msg
.
To
())
==
0
}
func
MessageGasValue
(
msg
Message
)
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Mul
(
msg
.
Gas
(),
msg
.
GasPrice
())
}
func
NewStateTransition
(
coinbase
*
state
.
StateObject
,
msg
Message
,
state
*
state
.
StateDB
,
block
*
types
.
Block
)
*
StateTransition
{
return
&
StateTransition
{
coinbase
.
Address
(),
msg
.
To
(),
msg
,
new
(
big
.
Int
),
new
(
big
.
Int
)
.
Set
(
msg
.
GasPrice
()),
msg
.
Value
(),
msg
.
Data
(),
state
,
block
,
coinbase
,
nil
,
nil
,
nil
}
return
&
StateTransition
{
coinbase
.
Address
(),
msg
.
To
(),
msg
,
new
(
big
.
Int
),
new
(
big
.
Int
)
.
Set
(
msg
.
GasPrice
()),
new
(
big
.
Int
),
msg
.
Value
(),
msg
.
Data
(),
state
,
block
,
coinbase
,
nil
,
nil
,
nil
}
}
func
(
self
*
StateTransition
)
VmEnv
()
vm
.
Environment
{
...
...
@@ -78,33 +82,16 @@ func (self *StateTransition) VmEnv() vm.Environment {
}
func
(
self
*
StateTransition
)
Coinbase
()
*
state
.
StateObject
{
if
self
.
cb
!=
nil
{
return
self
.
cb
}
self
.
cb
=
self
.
state
.
GetOrNewStateObject
(
self
.
coinbase
)
return
self
.
cb
return
self
.
state
.
GetOrNewStateObject
(
self
.
coinbase
)
}
func
(
self
*
StateTransition
)
From
()
*
state
.
StateObject
{
if
self
.
sen
!=
nil
{
return
self
.
sen
}
self
.
sen
=
self
.
state
.
GetOrNewStateObject
(
self
.
msg
.
From
())
return
self
.
sen
return
self
.
state
.
GetOrNewStateObject
(
self
.
msg
.
From
())
}
func
(
self
*
StateTransition
)
To
()
*
state
.
StateObject
{
if
self
.
msg
!=
nil
&&
MessageCreatesContract
(
self
.
msg
)
{
return
nil
}
if
self
.
rec
!=
nil
{
return
self
.
rec
}
self
.
rec
=
self
.
state
.
GetOrNewStateObject
(
self
.
msg
.
To
())
return
self
.
rec
return
self
.
state
.
GetOrNewStateObject
(
self
.
msg
.
To
())
}
func
(
self
*
StateTransition
)
UseGas
(
amount
*
big
.
Int
)
error
{
...
...
@@ -124,8 +111,8 @@ func (self *StateTransition) BuyGas() error {
var
err
error
sender
:=
self
.
From
()
if
sender
.
Balance
()
.
Cmp
(
self
.
msg
.
GasValue
(
))
<
0
{
return
fmt
.
Errorf
(
"Insufficient funds to pre-pay gas. Req %v, has %v"
,
self
.
msg
.
GasValue
(
),
sender
.
Balance
())
if
sender
.
Balance
()
.
Cmp
(
MessageGasValue
(
self
.
msg
))
<
0
{
return
fmt
.
Errorf
(
"Insufficient funds to pre-pay gas. Req %v, has %v"
,
MessageGasValue
(
self
.
msg
),
sender
.
Balance
())
}
coinbase
:=
self
.
Coinbase
()
...
...
@@ -135,20 +122,12 @@ func (self *StateTransition) BuyGas() error {
}
self
.
AddGas
(
self
.
msg
.
Gas
())
sender
.
SubAmount
(
self
.
msg
.
GasValue
())
self
.
initialGas
.
Set
(
self
.
msg
.
Gas
())
sender
.
SubAmount
(
MessageGasValue
(
self
.
msg
))
return
nil
}
func
(
self
*
StateTransition
)
RefundGas
()
{
coinbase
,
sender
:=
self
.
Coinbase
(),
self
.
From
()
coinbase
.
RefundGas
(
self
.
gas
,
self
.
msg
.
GasPrice
())
// Return remaining gas
remaining
:=
new
(
big
.
Int
)
.
Mul
(
self
.
gas
,
self
.
msg
.
GasPrice
())
sender
.
AddAmount
(
remaining
)
}
func
(
self
*
StateTransition
)
preCheck
()
(
err
error
)
{
var
(
msg
=
self
.
msg
...
...
@@ -168,7 +147,7 @@ func (self *StateTransition) preCheck() (err error) {
return
nil
}
func
(
self
*
StateTransition
)
TransitionState
()
(
err
error
)
{
func
(
self
*
StateTransition
)
TransitionState
()
(
ret
[]
byte
,
err
error
)
{
statelogger
.
Debugf
(
"(~) %x
\n
"
,
self
.
msg
.
Hash
())
// XXX Transactions after this point are considered valid.
...
...
@@ -204,7 +183,6 @@ func (self *StateTransition) TransitionState() (err error) {
return
}
var
ret
[]
byte
vmenv
:=
self
.
VmEnv
()
var
ref
vm
.
ClosureRef
if
MessageCreatesContract
(
msg
)
{
...
...
@@ -231,3 +209,26 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
return
contract
}
func
(
self
*
StateTransition
)
RefundGas
()
{
coinbaseSub
:=
new
(
big
.
Int
)
.
Set
(
self
.
gas
)
uhalf
:=
new
(
big
.
Int
)
.
Div
(
self
.
GasUsed
(),
ethutil
.
Big2
)
for
addr
,
refs
:=
range
self
.
state
.
Refunds
()
{
for
_
,
ref
:=
range
refs
{
coinbaseSub
.
Add
(
self
.
gas
,
ref
)
refund
:=
ethutil
.
BigMin
(
uhalf
,
ref
)
self
.
state
.
AddBalance
([]
byte
(
addr
),
refund
.
Mul
(
refund
,
self
.
msg
.
GasPrice
()))
}
}
coinbase
,
sender
:=
self
.
Coinbase
(),
self
.
From
()
coinbase
.
RefundGas
(
coinbaseSub
,
self
.
msg
.
GasPrice
())
// Return remaining gas
remaining
:=
new
(
big
.
Int
)
.
Mul
(
self
.
gas
,
self
.
msg
.
GasPrice
())
sender
.
AddAmount
(
remaining
)
}
func
(
self
*
StateTransition
)
GasUsed
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Sub
(
self
.
initialGas
,
self
.
gas
)
}
core/types/transaction.go
View file @
198cc693
...
...
@@ -46,15 +46,6 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
return
tx
}
func
(
self
*
Transaction
)
GasValue
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Mul
(
self
.
gas
,
self
.
gasPrice
)
}
func
(
self
*
Transaction
)
TotalValue
()
*
big
.
Int
{
v
:=
self
.
GasValue
()
return
v
.
Add
(
v
,
self
.
value
)
}
func
(
tx
*
Transaction
)
Hash
()
[]
byte
{
data
:=
[]
interface
{}{
tx
.
Nonce
,
tx
.
gasPrice
,
tx
.
gas
,
tx
.
recipient
,
tx
.
Value
,
tx
.
Data
}
...
...
state/state.go
View file @
198cc693
...
...
@@ -23,14 +23,14 @@ type StateDB struct {
manifest
*
Manifest
refund
map
[
string
][]
refund
refund
map
[
string
][]
*
big
.
Int
logs
Logs
}
// Create a new state from a given trie
func
New
(
trie
*
trie
.
Trie
)
*
StateDB
{
return
&
StateDB
{
Trie
:
trie
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
manifest
:
NewManifest
(),
refund
:
make
(
map
[
string
][]
refund
)}
return
&
StateDB
{
Trie
:
trie
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
manifest
:
NewManifest
(),
refund
:
make
(
map
[
string
][]
*
big
.
Int
)}
}
func
(
self
*
StateDB
)
EmptyLogs
()
{
...
...
@@ -55,12 +55,8 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
return
ethutil
.
Big0
}
type
refund
struct
{
gas
,
price
*
big
.
Int
}
func
(
self
*
StateDB
)
Refund
(
addr
[]
byte
,
gas
,
price
*
big
.
Int
)
{
self
.
refund
[
string
(
addr
)]
=
append
(
self
.
refund
[
string
(
addr
)],
refund
{
gas
,
price
})
func
(
self
*
StateDB
)
Refund
(
addr
[]
byte
,
gas
*
big
.
Int
)
{
self
.
refund
[
string
(
addr
)]
=
append
(
self
.
refund
[
string
(
addr
)],
gas
)
}
func
(
self
*
StateDB
)
AddBalance
(
addr
[]
byte
,
amount
*
big
.
Int
)
{
...
...
@@ -273,23 +269,17 @@ func (s *StateDB) Sync() {
func
(
self
*
StateDB
)
Empty
()
{
self
.
stateObjects
=
make
(
map
[
string
]
*
StateObject
)
self
.
refund
=
make
(
map
[
string
][]
refund
)
self
.
refund
=
make
(
map
[
string
][]
*
big
.
Int
)
}
func
(
self
*
StateDB
)
Refunds
()
map
[
string
][]
*
big
.
Int
{
return
self
.
refund
}
func
(
self
*
StateDB
)
Update
(
gasUsed
*
big
.
Int
)
{
var
deleted
bool
// Refund any gas that's left
// XXX THIS WILL CHANGE IN POC8
uhalf
:=
new
(
big
.
Int
)
.
Div
(
gasUsed
,
ethutil
.
Big2
)
for
addr
,
refs
:=
range
self
.
refund
{
for
_
,
ref
:=
range
refs
{
refund
:=
ethutil
.
BigMin
(
uhalf
,
ref
.
gas
)
self
.
GetStateObject
([]
byte
(
addr
))
.
AddBalance
(
refund
.
Mul
(
refund
,
ref
.
price
))
}
}
self
.
refund
=
make
(
map
[
string
][]
refund
)
self
.
refund
=
make
(
map
[
string
][]
*
big
.
Int
)
for
_
,
stateObject
:=
range
self
.
stateObjects
{
if
stateObject
.
remove
{
...
...
tests/helper/vm.go
View file @
198cc693
...
...
@@ -44,6 +44,7 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
env
.
time
=
ethutil
.
Big
(
envValues
[
"currentTimestamp"
])
.
Int64
()
env
.
difficulty
=
ethutil
.
Big
(
envValues
[
"currentDifficulty"
])
env
.
gasLimit
=
ethutil
.
Big
(
envValues
[
"currentGasLimit"
])
env
.
Gas
=
new
(
big
.
Int
)
return
env
}
...
...
@@ -110,7 +111,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log
return
ret
,
vmenv
.
logs
,
vmenv
.
Gas
,
err
}
func
RunState
(
state
*
state
.
StateDB
,
env
,
tx
map
[
string
]
string
)
([]
byte
,
state
.
Logs
,
*
big
.
Int
,
error
)
{
func
RunState
(
state
db
*
state
.
StateDB
,
env
,
tx
map
[
string
]
string
)
([]
byte
,
state
.
Logs
,
*
big
.
Int
,
error
)
{
var
(
keyPair
,
_
=
crypto
.
NewKeyPairFromSec
([]
byte
(
ethutil
.
Hex2Bytes
(
tx
[
"secretKey"
])))
to
=
FromHex
(
tx
[
"to"
])
...
...
@@ -118,13 +119,39 @@ func RunState(state *state.StateDB, env, tx map[string]string) ([]byte, state.Lo
gas
=
ethutil
.
Big
(
tx
[
"gasLimit"
])
price
=
ethutil
.
Big
(
tx
[
"gasPrice"
])
value
=
ethutil
.
Big
(
tx
[
"value"
])
caddr
=
FromHex
(
env
[
"currentCoinbase"
])
)
caller
:=
state
.
GetOrNewStateObject
(
keyPair
.
Address
())
coinbase
:=
statedb
.
GetOrNewStateObject
(
caddr
)
coinbase
.
SetGasPool
(
ethutil
.
Big
(
env
[
"currentGasLimit"
]))
vmenv
:=
NewEnvFromMap
(
state
,
env
,
tx
)
vmenv
.
origin
=
caller
.
Address
()
ret
,
err
:=
vmenv
.
Call
(
caller
,
to
,
data
,
gas
,
price
,
value
)
message
:=
NewMessage
(
keyPair
.
Address
(),
to
,
data
,
value
,
gas
,
price
)
Log
.
DebugDetailf
(
"message{ to: %x, from %x, value: %v, gas: %v, price: %v }
\n
"
,
message
.
to
[
:
4
],
message
.
from
[
:
4
],
message
.
value
,
message
.
gas
,
message
.
price
)
st
:=
core
.
NewStateTransition
(
coinbase
,
message
,
statedb
,
nil
)
vmenv
:=
NewEnvFromMap
(
statedb
,
env
,
tx
)
vmenv
.
origin
=
keyPair
.
Address
()
st
.
Env
=
vmenv
ret
,
err
:=
st
.
TransitionState
()
statedb
.
Update
(
vmenv
.
Gas
)
return
ret
,
vmenv
.
logs
,
vmenv
.
Gas
,
err
}
type
Message
struct
{
from
,
to
[]
byte
value
,
gas
,
price
*
big
.
Int
data
[]
byte
}
func
NewMessage
(
from
,
to
,
data
[]
byte
,
value
,
gas
,
price
*
big
.
Int
)
Message
{
return
Message
{
from
,
to
,
value
,
gas
,
price
,
data
}
}
func
(
self
Message
)
Hash
()
[]
byte
{
return
nil
}
func
(
self
Message
)
From
()
[]
byte
{
return
self
.
from
}
func
(
self
Message
)
To
()
[]
byte
{
return
self
.
to
}
func
(
self
Message
)
GasPrice
()
*
big
.
Int
{
return
self
.
price
}
func
(
self
Message
)
Gas
()
*
big
.
Int
{
return
self
.
gas
}
func
(
self
Message
)
Value
()
*
big
.
Int
{
return
self
.
value
}
func
(
self
Message
)
Nonce
()
uint64
{
return
0
}
func
(
self
Message
)
Data
()
[]
byte
{
return
self
.
data
}
tests/vm/gh_test.go
View file @
198cc693
...
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/tests/helper"
)
...
...
@@ -76,11 +77,18 @@ func RunVmTest(p string, t *testing.T) {
tests
:=
make
(
map
[
string
]
VmTest
)
helper
.
CreateFileTests
(
t
,
p
,
&
tests
)
helper
.
Logger
.
SetLogLevel
(
5
)
for
name
,
test
:=
range
tests
{
if
name
!=
"ABAcalls1"
{
continue
}
statedb
:=
state
.
New
(
helper
.
NewTrie
())
for
addr
,
account
:=
range
test
.
Pre
{
obj
:=
StateObjectFromAccount
(
addr
,
account
)
statedb
.
SetStateObject
(
obj
)
for
a
,
v
:=
range
account
.
Storage
{
obj
.
SetState
(
helper
.
FromHex
(
a
),
ethutil
.
NewValue
(
helper
.
FromHex
(
v
)))
}
}
// XXX Yeah, yeah...
...
...
@@ -129,6 +137,16 @@ func RunVmTest(p string, t *testing.T) {
for
addr
,
account
:=
range
test
.
Post
{
obj
:=
statedb
.
GetStateObject
(
helper
.
FromHex
(
addr
))
if
obj
==
nil
{
continue
}
if
len
(
test
.
Exec
)
==
0
{
if
obj
.
Balance
()
.
Cmp
(
ethutil
.
Big
(
account
.
Balance
))
!=
0
{
t
.
Errorf
(
"%s's : (%x) balance failed. Expected %v, got %v => %v
\n
"
,
name
,
obj
.
Address
()[
:
4
],
account
.
Balance
,
obj
.
Balance
(),
new
(
big
.
Int
)
.
Sub
(
ethutil
.
Big
(
account
.
Balance
),
obj
.
Balance
()))
}
}
for
addr
,
value
:=
range
account
.
Storage
{
v
:=
obj
.
GetState
(
helper
.
FromHex
(
addr
))
.
Bytes
()
vexp
:=
helper
.
FromHex
(
value
)
...
...
@@ -149,6 +167,7 @@ func RunVmTest(p string, t *testing.T) {
}
}
}
logger
.
Flush
()
}
// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail.
...
...
@@ -212,7 +231,12 @@ func TestStateRecursiveCreate(t *testing.T) {
RunVmTest
(
fn
,
t
)
}
func
TestStateSpecial
Test
(
t
*
testing
.
T
)
{
func
TestStateSpecial
(
t
*
testing
.
T
)
{
const
fn
=
"../files/StateTests/stSpecialTest.json"
RunVmTest
(
fn
,
t
)
}
func
TestStateRefund
(
t
*
testing
.
T
)
{
const
fn
=
"../files/StateTests/stRefundTest.json"
RunVmTest
(
fn
,
t
)
}
vm/common.go
View file @
198cc693
...
...
@@ -37,7 +37,7 @@ var (
GasLog
=
big
.
NewInt
(
32
)
GasSha256
=
big
.
NewInt
(
50
)
GasRipemd
=
big
.
NewInt
(
50
)
GasEcrecover
=
big
.
NewInt
(
1
00
)
GasEcrecover
=
big
.
NewInt
(
5
00
)
Pow256
=
ethutil
.
BigPow
(
2
,
256
)
...
...
vm/vm_debug.go
View file @
198cc693
...
...
@@ -2,6 +2,7 @@ package vm
import
(
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -112,7 +113,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
return
closure
.
Return
(
nil
),
nil
}
vmlogger
.
Debugf
(
"(%d)
%x gas: %v (d) %x
\n
"
,
self
.
env
.
Depth
()
,
closure
.
Address
(),
closure
.
Gas
,
callData
)
vmlogger
.
Debugf
(
"(%d)
(%x) %x gas: %v (d) %x
\n
"
,
self
.
env
.
Depth
(),
caller
.
Address
()[
:
4
]
,
closure
.
Address
(),
closure
.
Gas
,
callData
)
for
{
prevStep
=
step
...
...
@@ -185,11 +186,11 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
// 0 => non 0
mult
=
ethutil
.
Big3
}
else
if
val
.
BigInt
()
.
Cmp
(
ethutil
.
Big0
)
!=
0
&&
len
(
y
.
Bytes
())
==
0
{
statedb
.
Refund
(
c
losure
.
caller
.
Address
(),
GasSStoreRefund
,
closure
.
Price
)
statedb
.
Refund
(
c
aller
.
Address
(),
GasSStoreRefund
)
mult
=
ethutil
.
Big0
}
else
{
// non 0 => non 0
// non 0 => non 0
(or 0 => 0)
mult
=
ethutil
.
Big1
}
gas
.
Set
(
new
(
big
.
Int
)
.
Mul
(
mult
,
GasSStore
))
...
...
@@ -660,7 +661,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
cOff
=
0
l
=
0
}
else
if
cOff
+
l
>
size
{
l
=
0
l
=
uint64
(
math
.
Min
(
float64
(
cOff
+
l
),
float64
(
size
)))
}
codeCopy
:=
code
[
cOff
:
cOff
+
l
]
...
...
@@ -776,10 +777,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
val
,
loc
:=
stack
.
Popn
()
statedb
.
SetState
(
closure
.
Address
(),
loc
.
Bytes
(),
val
)
// Debug sessions are allowed to run without message
if
closure
.
message
!=
nil
{
closure
.
message
.
AddStorageChange
(
loc
.
Bytes
())
}
closure
.
message
.
AddStorageChange
(
loc
.
Bytes
())
self
.
Printf
(
" {0x%x : 0x%x}"
,
loc
.
Bytes
(),
val
.
Bytes
())
case
JUMP
:
...
...
@@ -898,10 +896,12 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
return
closure
.
Return
(
ret
),
nil
case
SUICIDE
:
receiver
:=
statedb
.
GetOrNewStateObject
(
stack
.
Pop
()
.
Bytes
())
balance
:=
statedb
.
GetBalance
(
closure
.
Address
())
self
.
Printf
(
" => (%x) %v"
,
receiver
.
Address
()[
:
4
],
balance
)
receiver
.
AddAmount
(
statedb
.
GetBalance
(
closure
.
Address
())
)
receiver
.
AddAmount
(
balance
)
statedb
.
Delete
(
closure
.
Address
())
fallthrough
...
...
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