added a transfer method to vm env
This commit is contained in:
parent
27cb0750c1
commit
b5beb1aac1
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
2
peer.go
2
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(),
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
2
vm/vm.go
2
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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user