aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-07-10 23:58:16 +0800
committerobscuren <geffobscura@gmail.com>2014-07-10 23:58:16 +0800
commit04561c4ddc363189bdb7377a271d6a734f09eae1 (patch)
tree0c2bc6ac9b5ef3563b527ab4bd2da9bba7f4ea47
parent9688ebef523fdd368f7d0596f4529b7e3bc26775 (diff)
downloadgo-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar.gz
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar.bz2
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar.lz
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar.xz
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.tar.zst
go-tangerine-04561c4ddc363189bdb7377a271d6a734f09eae1.zip
Updated VM & added helper methods to state
* VM BALANCE opcode updated to pop 1 item and use that to retrieve the address' balance * GetBalance and GetNonce on state that'll always return something valid
-rw-r--r--ethchain/state.go151
-rw-r--r--ethchain/vm.go20
2 files changed, 101 insertions, 70 deletions
diff --git a/ethchain/state.go b/ethchain/state.go
index d93ab3e01..6d45c9e32 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -26,79 +26,36 @@ func NewState(trie *ethtrie.Trie) *State {
return &State{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
}
-// Resets the trie and all siblings
-func (s *State) Reset() {
- s.trie.Undo()
-
- // Reset all nested states
- for _, stateObject := range s.stateObjects {
- if stateObject.state == nil {
- continue
- }
-
- //stateObject.state.Reset()
- stateObject.Reset()
- }
-
- s.Empty()
+// Iterate over each storage address and yield callback
+func (s *State) EachStorage(cb ethtrie.EachCallback) {
+ it := s.trie.NewIterator()
+ it.Each(cb)
}
-// Syncs the trie and all siblings
-func (s *State) Sync() {
- // Sync all nested states
- for _, stateObject := range s.stateObjects {
- s.UpdateStateObject(stateObject)
-
- if stateObject.state == nil {
- continue
- }
-
- stateObject.state.Sync()
+// Retrieve the balance from the given address or 0 if object not found
+func (self *State) GetBalance(addr []byte) *big.Int {
+ stateObject := self.GetStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Amount
}
- s.trie.Sync()
-
- s.Empty()
-}
-
-func (self *State) Empty() {
- self.stateObjects = make(map[string]*StateObject)
+ return ethutil.Big0
}
-func (self *State) Update() {
- for _, stateObject := range self.stateObjects {
- if stateObject.remove {
- self.DeleteStateObject(stateObject)
- } else {
- stateObject.Sync()
-
- self.UpdateStateObject(stateObject)
- }
- }
-
- // FIXME trie delete is broken
- valid, t2 := ethtrie.ParanoiaCheck(self.trie)
- if !valid {
- self.trie = t2
+func (self *State) GetNonce(addr []byte) uint64 {
+ stateObject := self.GetStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Nonce
}
-}
-// Purges the current trie.
-func (s *State) Purge() int {
- return s.trie.NewIterator().Purge()
+ return 0
}
-func (s *State) EachStorage(cb ethtrie.EachCallback) {
- it := s.trie.NewIterator()
- it.Each(cb)
-}
-
-func (self *State) ResetStateObject(stateObject *StateObject) {
- delete(self.stateObjects, string(stateObject.Address()))
-
- stateObject.state.Reset()
-}
+//
+// Setting, updating & deleting state object methods
+//
+// Update the given state object and apply it to state trie
func (self *State) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
@@ -109,12 +66,14 @@ func (self *State) UpdateStateObject(stateObject *StateObject) {
self.manifest.AddObjectChange(stateObject)
}
+// Delete the given state object and delete it from the state trie
func (self *State) DeleteStateObject(stateObject *StateObject) {
self.trie.Delete(string(stateObject.Address()))
delete(self.stateObjects, string(stateObject.Address()))
}
+// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
stateObject := self.stateObjects[string(addr)]
if stateObject != nil {
@@ -132,6 +91,7 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
return stateObject
}
+// Retrieve a state object or create a new state object if nil
func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
@@ -141,6 +101,7 @@ func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
return stateObject
}
+// Create a state object whether it exist in the trie or not
func (self *State) NewStateObject(addr []byte) *StateObject {
statelogger.Infof("(+) %x\n", addr)
@@ -150,10 +111,15 @@ func (self *State) NewStateObject(addr []byte) *StateObject {
return stateObject
}
+// Deprecated
func (self *State) GetAccount(addr []byte) *StateObject {
return self.GetOrNewStateObject(addr)
}
+//
+// Setting, copying of the state methods
+//
+
func (s *State) Cmp(other *State) bool {
return s.trie.Cmp(other.trie)
}
@@ -181,14 +147,67 @@ func (self *State) Set(state *State) {
//*self = *state
}
-func (s *State) Put(key, object []byte) {
- s.trie.Update(string(key), string(object))
-}
-
func (s *State) Root() interface{} {
return s.trie.Root
}
+// Resets the trie and all siblings
+func (s *State) Reset() {
+ s.trie.Undo()
+
+ // Reset all nested states
+ for _, stateObject := range s.stateObjects {
+ if stateObject.state == nil {
+ continue
+ }
+
+ //stateObject.state.Reset()
+ stateObject.Reset()
+ }
+
+ s.Empty()
+}
+
+// Syncs the trie and all siblings
+func (s *State) Sync() {
+ // Sync all nested states
+ for _, stateObject := range s.stateObjects {
+ s.UpdateStateObject(stateObject)
+
+ if stateObject.state == nil {
+ continue
+ }
+
+ stateObject.state.Sync()
+ }
+
+ s.trie.Sync()
+
+ s.Empty()
+}
+
+func (self *State) Empty() {
+ self.stateObjects = make(map[string]*StateObject)
+}
+
+func (self *State) Update() {
+ for _, stateObject := range self.stateObjects {
+ if stateObject.remove {
+ self.DeleteStateObject(stateObject)
+ } else {
+ stateObject.Sync()
+
+ self.UpdateStateObject(stateObject)
+ }
+ }
+
+ // FIXME trie delete is broken
+ valid, t2 := ethtrie.ParanoiaCheck(self.trie)
+ if !valid {
+ self.trie = t2
+ }
+}
+
// Object manifest
//
// The object manifest is used to keep changes to the state so we can keep track of the changes
diff --git a/ethchain/vm.go b/ethchain/vm.go
index c63b5392f..f57d6a751 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -452,13 +452,26 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
data := ethcrypto.Sha3Bin(mem.Get(offset.Int64(), size.Int64()))
stack.Push(ethutil.BigD(data))
+
+ vm.Printf(" => %x", data)
// 0x30 range
case ADDRESS:
stack.Push(ethutil.BigD(closure.Object().Address()))
+
+ vm.Printf(" => %x", closure.Object().Address())
case BALANCE:
- stack.Push(closure.object.Amount)
+ require(1)
+
+ addr := stack.Pop().Bytes()
+ balance := vm.state.GetBalance(addr)
+
+ stack.Push(balance)
+
+ vm.Printf(" => %v (%x)", balance, addr)
case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
+
+ vm.Printf(" => %v", vm.vars.Origin)
case CALLER:
caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller))
@@ -712,7 +725,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(ethutil.BigFalse)
} else {
- //snapshot := vm.state.Copy()
+ snapshot := vm.state.Copy()
stateObject := vm.state.GetOrNewStateObject(addr.Bytes())
@@ -728,8 +741,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
vmlogger.Debugf("Closure execution failed. %v\n", err)
- //vm.state.Set(snapshot)
- vm.state.ResetStateObject(stateObject)
+ vm.state.Set(snapshot)
} else {
stack.Push(ethutil.BigTrue)