aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-10-22 21:22:21 +0800
committerobscuren <geffobscura@gmail.com>2014-10-22 21:22:21 +0800
commitb5beb1aac11af92bfe0f3ed7560b9eb08495ed09 (patch)
tree3f3fba73bca00f8c0a6c9f8bc29bca8ba36e991d
parent27cb0750c1deaed040876abdab1386a6687d7999 (diff)
downloaddexon-b5beb1aac11af92bfe0f3ed7560b9eb08495ed09.tar.gz
dexon-b5beb1aac11af92bfe0f3ed7560b9eb08495ed09.tar.zst
dexon-b5beb1aac11af92bfe0f3ed7560b9eb08495ed09.zip
added a transfer method to vm env
-rw-r--r--ethstate/dump.go2
-rw-r--r--ethstate/state.go2
-rw-r--r--ethstate/state_object.go40
-rw-r--r--peer.go2
-rw-r--r--tests/helper/vm.go5
-rw-r--r--tests/vm/gh_test.go6
-rw-r--r--vm/environment.go20
-rw-r--r--vm/execution.go16
-rw-r--r--vm/vm.go2
9 files changed, 59 insertions, 36 deletions
diff --git a/ethstate/dump.go b/ethstate/dump.go
index cdd4228b8..e7cbde48b 100644
--- a/ethstate/dump.go
+++ b/ethstate/dump.go
@@ -28,7 +28,7 @@ func (self *State) Dump() []byte {
self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) {
stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes())
- account := Account{Balance: stateObject.Balance.String(), Nonce: stateObject.Nonce, CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
+ account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.Nonce, CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
account.Storage = make(map[string]string)
stateObject.EachStorage(func(key string, value *ethutil.Value) {
diff --git a/ethstate/state.go b/ethstate/state.go
index 2efe2a311..59d2265a9 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -33,7 +33,7 @@ func New(trie *ethtrie.Trie) *State {
func (self *State) GetBalance(addr []byte) *big.Int {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- return stateObject.Balance
+ return stateObject.balance
}
return ethutil.Big0
diff --git a/ethstate/state_object.go b/ethstate/state_object.go
index a5b7c65e9..1ba005439 100644
--- a/ethstate/state_object.go
+++ b/ethstate/state_object.go
@@ -31,7 +31,7 @@ type StateObject struct {
// Address of the object
address []byte
// Shared attributes
- Balance *big.Int
+ balance *big.Int
codeHash []byte
Nonce uint64
// Contract related attributes
@@ -61,7 +61,7 @@ func NewStateObject(addr []byte) *StateObject {
// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter.
address := ethutil.Address(addr)
- object := &StateObject{address: address, Balance: new(big.Int), gasPool: new(big.Int)}
+ object := &StateObject{address: address, balance: new(big.Int), gasPool: new(big.Int)}
object.State = New(ethtrie.New(ethutil.Config.Db, ""))
object.storage = make(Storage)
object.gasPool = new(big.Int)
@@ -71,7 +71,7 @@ func NewStateObject(addr []byte) *StateObject {
func NewContract(address []byte, balance *big.Int, root []byte) *StateObject {
contract := NewStateObject(address)
- contract.Balance = balance
+ contract.balance = balance
contract.State = New(ethtrie.New(ethutil.Config.Db, string(root)))
return contract
@@ -86,7 +86,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject {
func (self *StateObject) MarkForDeletion() {
self.remove = true
- statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Balance)
+ statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance)
}
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
@@ -174,22 +174,26 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte{c.Code[pc.Int64()]})
}
-func (c *StateObject) AddAmount(amount *big.Int) {
- c.SetBalance(new(big.Int).Add(c.Balance, amount))
+func (c *StateObject) AddBalance(amount *big.Int) {
+ c.SetBalance(new(big.Int).Add(c.balance, amount))
- statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Balance, amount)
+ statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.balance, amount)
}
+func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) }
-func (c *StateObject) SubAmount(amount *big.Int) {
- c.SetBalance(new(big.Int).Sub(c.Balance, amount))
+func (c *StateObject) SubBalance(amount *big.Int) {
+ c.SetBalance(new(big.Int).Sub(c.balance, amount))
- statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Balance, amount)
+ statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.balance, amount)
}
+func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) }
func (c *StateObject) SetBalance(amount *big.Int) {
- c.Balance = amount
+ c.balance = amount
}
+func (self *StateObject) Balance() *big.Int { return self.balance }
+
//
// Gas setters and getters
//
@@ -198,8 +202,8 @@ func (c *StateObject) SetBalance(amount *big.Int) {
func (c *StateObject) ReturnGas(gas, price *big.Int) {}
func (c *StateObject) ConvertGas(gas, price *big.Int) error {
total := new(big.Int).Mul(gas, price)
- if total.Cmp(c.Balance) > 0 {
- return fmt.Errorf("insufficient amount: %v, %v", c.Balance, total)
+ if total.Cmp(c.balance) > 0 {
+ return fmt.Errorf("insufficient amount: %v, %v", c.balance, total)
}
c.SubAmount(total)
@@ -232,12 +236,12 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
- self.Balance.Sub(self.Balance, rGas)
+ self.balance.Sub(self.balance, rGas)
}
func (self *StateObject) Copy() *StateObject {
stateObject := NewStateObject(self.Address())
- stateObject.Balance.Set(self.Balance)
+ stateObject.balance.Set(self.balance)
stateObject.codeHash = ethutil.CopyBytes(self.codeHash)
stateObject.Nonce = self.Nonce
if self.State != nil {
@@ -281,7 +285,7 @@ func (self *StateObject) Object() *StateObject {
// Debug stuff
func (self *StateObject) CreateOutputForDiff() {
- fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.Balance.Bytes(), self.Nonce)
+ fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.Nonce)
self.EachStorage(func(addr string, value *ethutil.Value) {
fmt.Printf("%x %x\n", addr, value.Bytes())
})
@@ -300,7 +304,7 @@ func (c *StateObject) RlpEncode() []byte {
root = ""
}
- return ethutil.Encode([]interface{}{c.Nonce, c.Balance, root, c.CodeHash()})
+ return ethutil.Encode([]interface{}{c.Nonce, c.balance, root, c.CodeHash()})
}
func (c *StateObject) CodeHash() ethutil.Bytes {
@@ -316,7 +320,7 @@ func (c *StateObject) RlpDecode(data []byte) {
decoder := ethutil.NewValueFromBytes(data)
c.Nonce = decoder.Get(0).Uint()
- c.Balance = decoder.Get(1).BigInt()
+ c.balance = decoder.Get(1).BigInt()
c.State = New(ethtrie.New(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value)
c.gasPool = new(big.Int)
diff --git a/peer.go b/peer.go
index 04ff4af39..557c436f6 100644
--- a/peer.go
+++ b/peer.go
@@ -674,7 +674,7 @@ func (p *Peer) pushPeers() {
func (self *Peer) pushStatus() {
msg := ethwire.NewMessage(ethwire.MsgStatusTy, []interface{}{
- //uint32(ProtocolVersion),
+ uint32(ProtocolVersion),
uint32(NetVersion),
self.ethereum.ChainManager().TD,
self.ethereum.ChainManager().CurrentBlock.Hash(),
diff --git a/tests/helper/vm.go b/tests/helper/vm.go
index a3d54de23..06c3d4eca 100644
--- a/tests/helper/vm.go
+++ b/tests/helper/vm.go
@@ -50,11 +50,14 @@ func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) BlockHash() []byte { return nil }
func (self *Env) State() *ethstate.State { return self.state }
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
+func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error {
+ return nil
+}
func RunVm(state *ethstate.State, env, exec map[string]string) ([]byte, *big.Int, error) {
address := FromHex(exec["address"])
caller := state.GetOrNewStateObject(FromHex(exec["caller"]))
- caller.Balance = ethutil.Big(exec["value"])
+ caller.SetBalance(ethutil.Big(exec["value"]))
evm := vm.New(NewEnvFromMap(state, env, exec), vm.DebugVmTy)
diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go
index f27cc7af3..64f279d8d 100644
--- a/tests/vm/gh_test.go
+++ b/tests/vm/gh_test.go
@@ -18,7 +18,7 @@ type Account struct {
func StateObjectFromAccount(addr string, account Account) *ethstate.StateObject {
obj := ethstate.NewStateObject(ethutil.Hex2Bytes(addr))
- obj.Balance = ethutil.Big(account.Balance)
+ obj.SetBalance(ethutil.Big(account.Balance))
if ethutil.IsHex(account.Code) {
account.Code = account.Code[2:]
@@ -44,9 +44,6 @@ func RunVmTest(p string, t *testing.T) {
helper.CreateFileTests(t, p, &tests)
for name, test := range tests {
- if name != "CallRecursiveBomb" {
- continue
- }
state := ethstate.New(helper.NewTrie())
for addr, account := range test.Pre {
obj := StateObjectFromAccount(addr, account)
@@ -92,7 +89,6 @@ func TestVMArithmetic(t *testing.T) {
}
func TestVMSystemOperation(t *testing.T) {
- helper.Logger.SetLogLevel(5)
const fn = "../files/vmtests/vmSystemOperationsTest.json"
RunVmTest(fn, t)
}
diff --git a/vm/environment.go b/vm/environment.go
index 2d933b65c..23b46c5df 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -1,6 +1,7 @@
package vm
import (
+ "errors"
"math/big"
"github.com/ethereum/eth-go/ethstate"
@@ -18,9 +19,28 @@ type Environment interface {
Difficulty() *big.Int
BlockHash() []byte
GasLimit() *big.Int
+ Transfer(from, to Account, amount *big.Int) error
}
type Object interface {
GetStorage(key *big.Int) *ethutil.Value
SetStorage(key *big.Int, value *ethutil.Value)
}
+
+type Account interface {
+ SubBalance(amount *big.Int)
+ AddBalance(amount *big.Int)
+ Balance() *big.Int
+}
+
+// generic transfer method
+func Transfer(from, to Account, amount *big.Int) error {
+ if from.Balance().Cmp(amount) < 0 {
+ return errors.New("Insufficient balance in account")
+ }
+
+ from.SubBalance(amount)
+ to.AddBalance(amount)
+
+ return nil
+}
diff --git a/vm/execution.go b/vm/execution.go
index 6bed43026..4c4bd1e3c 100644
--- a/vm/execution.go
+++ b/vm/execution.go
@@ -48,17 +48,17 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte,
Value: self.value,
})
- object := caller.Object()
- if object.Balance.Cmp(self.value) < 0 {
+ from, to := caller.Object(), env.State().GetOrNewStateObject(self.address)
+ err = env.Transfer(from, to, self.value)
+ if err != nil {
caller.ReturnGas(self.Gas, self.price)
- err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, object.Balance)
+ err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance)
} else {
- stateObject := env.State().GetOrNewStateObject(self.address)
- self.object = stateObject
+ self.object = to
- caller.Object().SubAmount(self.value)
- stateObject.AddAmount(self.value)
+ //caller.Object().SubAmount(self.value)
+ //stateObject.AddAmount(self.value)
// Pre-compiled contracts (address.go) 1, 2 & 3.
naddr := ethutil.BigD(caddr).Uint64()
@@ -69,7 +69,7 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte,
}
} else {
// Create a new callable closure
- c := NewClosure(msg, caller, stateObject, code, self.Gas, self.price)
+ c := NewClosure(msg, caller, to, code, self.Gas, self.price)
c.exe = self
if self.vm.Depth() == MaxCallDepth {
diff --git a/vm/vm.go b/vm/vm.go
index 72d4f7131..b5c7c0e21 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -692,7 +692,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
receiver := self.env.State().GetOrNewStateObject(stack.Pop().Bytes())
- receiver.AddAmount(closure.object.Balance)
+ receiver.AddAmount(closure.object.Balance())
closure.object.MarkForDeletion()