Skip to content

Commit 198cc69

Browse files
committed
Gas corrections and vm fixes
1 parent 5ad473d commit 198cc69

File tree

8 files changed

+116
-83
lines changed

8 files changed

+116
-83
lines changed

core/block_manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ done:
115115

116116
cb := state.GetStateObject(coinbase.Address())
117117
st := NewStateTransition(cb, tx, state, block)
118-
err = st.TransitionState()
118+
_, err = st.TransitionState()
119119
if err != nil {
120120
switch {
121121
case IsNonceErr(err):

core/state_transition.go

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type StateTransition struct {
3131
coinbase, receiver []byte
3232
msg Message
3333
gas, gasPrice *big.Int
34+
initialGas *big.Int
3435
value *big.Int
3536
data []byte
3637
state *state.StateDB
@@ -47,7 +48,6 @@ type Message interface {
4748
From() []byte
4849
To() []byte
4950

50-
GasValue() *big.Int
5151
GasPrice() *big.Int
5252
Gas() *big.Int
5353
Value() *big.Int
@@ -65,8 +65,12 @@ func MessageCreatesContract(msg Message) bool {
6565
return len(msg.To()) == 0
6666
}
6767

68+
func MessageGasValue(msg Message) *big.Int {
69+
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
70+
}
71+
6872
func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition {
69-
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}
73+
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}
7074
}
7175

7276
func (self *StateTransition) VmEnv() vm.Environment {
@@ -78,33 +82,16 @@ func (self *StateTransition) VmEnv() vm.Environment {
7882
}
7983

8084
func (self *StateTransition) Coinbase() *state.StateObject {
81-
if self.cb != nil {
82-
return self.cb
83-
}
84-
85-
self.cb = self.state.GetOrNewStateObject(self.coinbase)
86-
return self.cb
85+
return self.state.GetOrNewStateObject(self.coinbase)
8786
}
8887
func (self *StateTransition) From() *state.StateObject {
89-
if self.sen != nil {
90-
return self.sen
91-
}
92-
93-
self.sen = self.state.GetOrNewStateObject(self.msg.From())
94-
95-
return self.sen
88+
return self.state.GetOrNewStateObject(self.msg.From())
9689
}
9790
func (self *StateTransition) To() *state.StateObject {
9891
if self.msg != nil && MessageCreatesContract(self.msg) {
9992
return nil
10093
}
101-
102-
if self.rec != nil {
103-
return self.rec
104-
}
105-
106-
self.rec = self.state.GetOrNewStateObject(self.msg.To())
107-
return self.rec
94+
return self.state.GetOrNewStateObject(self.msg.To())
10895
}
10996

11097
func (self *StateTransition) UseGas(amount *big.Int) error {
@@ -124,8 +111,8 @@ func (self *StateTransition) BuyGas() error {
124111
var err error
125112

126113
sender := self.From()
127-
if sender.Balance().Cmp(self.msg.GasValue()) < 0 {
128-
return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", self.msg.GasValue(), sender.Balance())
114+
if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 {
115+
return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", MessageGasValue(self.msg), sender.Balance())
129116
}
130117

131118
coinbase := self.Coinbase()
@@ -135,20 +122,12 @@ func (self *StateTransition) BuyGas() error {
135122
}
136123

137124
self.AddGas(self.msg.Gas())
138-
sender.SubAmount(self.msg.GasValue())
125+
self.initialGas.Set(self.msg.Gas())
126+
sender.SubAmount(MessageGasValue(self.msg))
139127

140128
return nil
141129
}
142130

143-
func (self *StateTransition) RefundGas() {
144-
coinbase, sender := self.Coinbase(), self.From()
145-
coinbase.RefundGas(self.gas, self.msg.GasPrice())
146-
147-
// Return remaining gas
148-
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
149-
sender.AddAmount(remaining)
150-
}
151-
152131
func (self *StateTransition) preCheck() (err error) {
153132
var (
154133
msg = self.msg
@@ -168,7 +147,7 @@ func (self *StateTransition) preCheck() (err error) {
168147
return nil
169148
}
170149

171-
func (self *StateTransition) TransitionState() (err error) {
150+
func (self *StateTransition) TransitionState() (ret []byte, err error) {
172151
statelogger.Debugf("(~) %x\n", self.msg.Hash())
173152

174153
// XXX Transactions after this point are considered valid.
@@ -204,7 +183,6 @@ func (self *StateTransition) TransitionState() (err error) {
204183
return
205184
}
206185

207-
var ret []byte
208186
vmenv := self.VmEnv()
209187
var ref vm.ClosureRef
210188
if MessageCreatesContract(msg) {
@@ -231,3 +209,26 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
231209

232210
return contract
233211
}
212+
213+
func (self *StateTransition) RefundGas() {
214+
coinbaseSub := new(big.Int).Set(self.gas)
215+
uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2)
216+
for addr, refs := range self.state.Refunds() {
217+
for _, ref := range refs {
218+
coinbaseSub.Add(self.gas, ref)
219+
refund := ethutil.BigMin(uhalf, ref)
220+
self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice()))
221+
}
222+
}
223+
224+
coinbase, sender := self.Coinbase(), self.From()
225+
coinbase.RefundGas(coinbaseSub, self.msg.GasPrice())
226+
227+
// Return remaining gas
228+
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
229+
sender.AddAmount(remaining)
230+
}
231+
232+
func (self *StateTransition) GasUsed() *big.Int {
233+
return new(big.Int).Sub(self.initialGas, self.gas)
234+
}

core/types/transaction.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
4646
return tx
4747
}
4848

49-
func (self *Transaction) GasValue() *big.Int {
50-
return new(big.Int).Mul(self.gas, self.gasPrice)
51-
}
52-
53-
func (self *Transaction) TotalValue() *big.Int {
54-
v := self.GasValue()
55-
return v.Add(v, self.value)
56-
}
57-
5849
func (tx *Transaction) Hash() []byte {
5950
data := []interface{}{tx.Nonce, tx.gasPrice, tx.gas, tx.recipient, tx.Value, tx.Data}
6051

state/state.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ type StateDB struct {
2323

2424
manifest *Manifest
2525

26-
refund map[string][]refund
26+
refund map[string][]*big.Int
2727

2828
logs Logs
2929
}
3030

3131
// Create a new state from a given trie
3232
func New(trie *trie.Trie) *StateDB {
33-
return &StateDB{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string][]refund)}
33+
return &StateDB{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string][]*big.Int)}
3434
}
3535

3636
func (self *StateDB) EmptyLogs() {
@@ -55,12 +55,8 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
5555
return ethutil.Big0
5656
}
5757

58-
type refund struct {
59-
gas, price *big.Int
60-
}
61-
62-
func (self *StateDB) Refund(addr []byte, gas, price *big.Int) {
63-
self.refund[string(addr)] = append(self.refund[string(addr)], refund{gas, price})
58+
func (self *StateDB) Refund(addr []byte, gas *big.Int) {
59+
self.refund[string(addr)] = append(self.refund[string(addr)], gas)
6460
}
6561

6662
func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
@@ -273,23 +269,17 @@ func (s *StateDB) Sync() {
273269

274270
func (self *StateDB) Empty() {
275271
self.stateObjects = make(map[string]*StateObject)
276-
self.refund = make(map[string][]refund)
272+
self.refund = make(map[string][]*big.Int)
273+
}
274+
275+
func (self *StateDB) Refunds() map[string][]*big.Int {
276+
return self.refund
277277
}
278278

279279
func (self *StateDB) Update(gasUsed *big.Int) {
280280
var deleted bool
281281

282-
// Refund any gas that's left
283-
// XXX THIS WILL CHANGE IN POC8
284-
uhalf := new(big.Int).Div(gasUsed, ethutil.Big2)
285-
for addr, refs := range self.refund {
286-
for _, ref := range refs {
287-
refund := ethutil.BigMin(uhalf, ref.gas)
288-
289-
self.GetStateObject([]byte(addr)).AddBalance(refund.Mul(refund, ref.price))
290-
}
291-
}
292-
self.refund = make(map[string][]refund)
282+
self.refund = make(map[string][]*big.Int)
293283

294284
for _, stateObject := range self.stateObjects {
295285
if stateObject.remove {

tests/helper/vm.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
4444
env.time = ethutil.Big(envValues["currentTimestamp"]).Int64()
4545
env.difficulty = ethutil.Big(envValues["currentDifficulty"])
4646
env.gasLimit = ethutil.Big(envValues["currentGasLimit"])
47+
env.Gas = new(big.Int)
4748

4849
return env
4950
}
@@ -110,21 +111,47 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log
110111
return ret, vmenv.logs, vmenv.Gas, err
111112
}
112113

113-
func RunState(state *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
114+
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
114115
var (
115116
keyPair, _ = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(tx["secretKey"])))
116117
to = FromHex(tx["to"])
117118
data = FromHex(tx["data"])
118119
gas = ethutil.Big(tx["gasLimit"])
119120
price = ethutil.Big(tx["gasPrice"])
120121
value = ethutil.Big(tx["value"])
122+
caddr = FromHex(env["currentCoinbase"])
121123
)
122124

123-
caller := state.GetOrNewStateObject(keyPair.Address())
125+
coinbase := statedb.GetOrNewStateObject(caddr)
126+
coinbase.SetGasPool(ethutil.Big(env["currentGasLimit"]))
124127

125-
vmenv := NewEnvFromMap(state, env, tx)
126-
vmenv.origin = caller.Address()
127-
ret, err := vmenv.Call(caller, to, data, gas, price, value)
128+
message := NewMessage(keyPair.Address(), to, data, value, gas, price)
129+
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)
130+
st := core.NewStateTransition(coinbase, message, statedb, nil)
131+
vmenv := NewEnvFromMap(statedb, env, tx)
132+
vmenv.origin = keyPair.Address()
133+
st.Env = vmenv
134+
ret, err := st.TransitionState()
135+
statedb.Update(vmenv.Gas)
128136

129137
return ret, vmenv.logs, vmenv.Gas, err
130138
}
139+
140+
type Message struct {
141+
from, to []byte
142+
value, gas, price *big.Int
143+
data []byte
144+
}
145+
146+
func NewMessage(from, to, data []byte, value, gas, price *big.Int) Message {
147+
return Message{from, to, value, gas, price, data}
148+
}
149+
150+
func (self Message) Hash() []byte { return nil }
151+
func (self Message) From() []byte { return self.from }
152+
func (self Message) To() []byte { return self.to }
153+
func (self Message) GasPrice() *big.Int { return self.price }
154+
func (self Message) Gas() *big.Int { return self.gas }
155+
func (self Message) Value() *big.Int { return self.value }
156+
func (self Message) Nonce() uint64 { return 0 }
157+
func (self Message) Data() []byte { return self.data }

tests/vm/gh_test.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/ethereum/go-ethereum/core/types"
1010
"github.com/ethereum/go-ethereum/ethutil"
11+
"github.com/ethereum/go-ethereum/logger"
1112
"github.com/ethereum/go-ethereum/state"
1213
"github.com/ethereum/go-ethereum/tests/helper"
1314
)
@@ -76,11 +77,18 @@ func RunVmTest(p string, t *testing.T) {
7677
tests := make(map[string]VmTest)
7778
helper.CreateFileTests(t, p, &tests)
7879

80+
helper.Logger.SetLogLevel(5)
7981
for name, test := range tests {
82+
if name != "ABAcalls1" {
83+
continue
84+
}
8085
statedb := state.New(helper.NewTrie())
8186
for addr, account := range test.Pre {
8287
obj := StateObjectFromAccount(addr, account)
8388
statedb.SetStateObject(obj)
89+
for a, v := range account.Storage {
90+
obj.SetState(helper.FromHex(a), ethutil.NewValue(helper.FromHex(v)))
91+
}
8492
}
8593

8694
// XXX Yeah, yeah...
@@ -129,6 +137,16 @@ func RunVmTest(p string, t *testing.T) {
129137

130138
for addr, account := range test.Post {
131139
obj := statedb.GetStateObject(helper.FromHex(addr))
140+
if obj == nil {
141+
continue
142+
}
143+
144+
if len(test.Exec) == 0 {
145+
if obj.Balance().Cmp(ethutil.Big(account.Balance)) != 0 {
146+
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()))
147+
}
148+
}
149+
132150
for addr, value := range account.Storage {
133151
v := obj.GetState(helper.FromHex(addr)).Bytes()
134152
vexp := helper.FromHex(value)
@@ -149,6 +167,7 @@ func RunVmTest(p string, t *testing.T) {
149167
}
150168
}
151169
}
170+
logger.Flush()
152171
}
153172

154173
// 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) {
212231
RunVmTest(fn, t)
213232
}
214233

215-
func TestStateSpecialTest(t *testing.T) {
234+
func TestStateSpecial(t *testing.T) {
216235
const fn = "../files/StateTests/stSpecialTest.json"
217236
RunVmTest(fn, t)
218237
}
238+
239+
func TestStateRefund(t *testing.T) {
240+
const fn = "../files/StateTests/stRefundTest.json"
241+
RunVmTest(fn, t)
242+
}

vm/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ var (
3737
GasLog = big.NewInt(32)
3838
GasSha256 = big.NewInt(50)
3939
GasRipemd = big.NewInt(50)
40-
GasEcrecover = big.NewInt(100)
40+
GasEcrecover = big.NewInt(500)
4141

4242
Pow256 = ethutil.BigPow(2, 256)
4343

0 commit comments

Comments
 (0)