From 1e8b54abfb7129fcdf4812ad01b6a7cd61e4f65d Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Tue, 22 Jul 2014 11:54:48 +0200
Subject: Refactored state, state object and vm

* The State and StateObject have been moved to their own package
* The VM is moved to it's own package
---
 ethstate/state.go | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 ethstate/state.go

(limited to 'ethstate/state.go')

diff --git a/ethstate/state.go b/ethstate/state.go
new file mode 100644
index 000000000..a4b9b1e9c
--- /dev/null
+++ b/ethstate/state.go
@@ -0,0 +1,259 @@
+package ethstate
+
+import (
+	"github.com/ethereum/eth-go/ethcrypto"
+	"github.com/ethereum/eth-go/ethlog"
+	"github.com/ethereum/eth-go/ethtrie"
+	"github.com/ethereum/eth-go/ethutil"
+	"math/big"
+)
+
+var statelogger = ethlog.NewLogger("STATE")
+
+// States within the ethereum protocol are used to store anything
+// within the merkle trie. States take care of caching and storing
+// nested states. It's the general query interface to retrieve:
+// * Contracts
+// * Accounts
+type State struct {
+	// The trie for this structure
+	trie *ethtrie.Trie
+
+	stateObjects map[string]*StateObject
+
+	manifest *Manifest
+}
+
+// Create a new state from a given trie
+func NewState(trie *ethtrie.Trie) *State {
+	return &State{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
+}
+
+// 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
+	}
+
+	return ethutil.Big0
+}
+
+func (self *State) GetNonce(addr []byte) uint64 {
+	stateObject := self.GetStateObject(addr)
+	if stateObject != nil {
+		return stateObject.Nonce
+	}
+
+	return 0
+}
+
+//
+// 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()
+
+	ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)
+
+	self.trie.Update(string(addr), string(stateObject.RlpEncode()))
+
+	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 {
+	addr = ethutil.Address(addr)
+
+	stateObject := self.stateObjects[string(addr)]
+	if stateObject != nil {
+		return stateObject
+	}
+
+	data := self.trie.Get(string(addr))
+	if len(data) == 0 {
+		return nil
+	}
+
+	stateObject = NewStateObjectFromBytes(addr, []byte(data))
+	self.stateObjects[string(addr)] = 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 {
+		stateObject = self.NewStateObject(addr)
+	}
+
+	return stateObject
+}
+
+// Create a state object whether it exist in the trie or not
+func (self *State) NewStateObject(addr []byte) *StateObject {
+	addr = ethutil.Address(addr)
+
+	statelogger.Infof("(+) %x\n", addr)
+
+	stateObject := NewStateObject(addr)
+	self.stateObjects[string(addr)] = 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)
+}
+
+func (self *State) Copy() *State {
+	if self.trie != nil {
+		state := NewState(self.trie.Copy())
+		for k, stateObject := range self.stateObjects {
+			state.stateObjects[k] = stateObject.Copy()
+		}
+
+		return state
+	}
+
+	return nil
+}
+
+func (self *State) Set(state *State) {
+	if state == nil {
+		panic("Tried setting 'state' to nil through 'Set'")
+	}
+
+	self.trie = state.trie
+	self.stateObjects = state.stateObjects
+}
+
+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 {
+		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root)
+
+		self.trie = t2
+	}
+}
+
+// Debug stuff
+func (self *State) CreateOutputForDiff() {
+	for _, stateObject := range self.stateObjects {
+		stateObject.CreateOutputForDiff()
+	}
+}
+
+func (self *State) Manifest() *Manifest {
+	return self.manifest
+}
+
+// Object manifest
+//
+// The object manifest is used to keep changes to the state so we can keep track of the changes
+// that occurred during a state transitioning phase.
+type Manifest struct {
+	// XXX These will be handy in the future. Not important for now.
+	objectAddresses  map[string]bool
+	storageAddresses map[string]map[string]bool
+
+	objectChanges  map[string]*StateObject
+	storageChanges map[string]map[string]*big.Int
+}
+
+func NewManifest() *Manifest {
+	m := &Manifest{objectAddresses: make(map[string]bool), storageAddresses: make(map[string]map[string]bool)}
+	m.Reset()
+
+	return m
+}
+
+func (m *Manifest) Reset() {
+	m.objectChanges = make(map[string]*StateObject)
+	m.storageChanges = make(map[string]map[string]*big.Int)
+}
+
+func (m *Manifest) AddObjectChange(stateObject *StateObject) {
+	m.objectChanges[string(stateObject.Address())] = stateObject
+}
+
+func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
+	if m.storageChanges[string(stateObject.Address())] == nil {
+		m.storageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
+	}
+
+	m.storageChanges[string(stateObject.Address())][string(storageAddr)] = storage
+}
-- 
cgit v1.2.3


From 32d125131f602d63f66ee7eb09439074f0b94a91 Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Thu, 24 Jul 2014 12:04:15 +0200
Subject: Refactored to new state and vm

---
 ethstate/state.go | 52 ++++++++++++++++++++++++++--------------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

(limited to 'ethstate/state.go')

diff --git a/ethstate/state.go b/ethstate/state.go
index a4b9b1e9c..51b585d4d 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -17,7 +17,7 @@ var statelogger = ethlog.NewLogger("STATE")
 // * Accounts
 type State struct {
 	// The trie for this structure
-	trie *ethtrie.Trie
+	Trie *ethtrie.Trie
 
 	stateObjects map[string]*StateObject
 
@@ -26,7 +26,7 @@ type State struct {
 
 // Create a new state from a given trie
 func NewState(trie *ethtrie.Trie) *State {
-	return &State{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
+	return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
 }
 
 // Retrieve the balance from the given address or 0 if object not found
@@ -58,14 +58,14 @@ func (self *State) UpdateStateObject(stateObject *StateObject) {
 
 	ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)
 
-	self.trie.Update(string(addr), string(stateObject.RlpEncode()))
+	self.Trie.Update(string(addr), string(stateObject.RlpEncode()))
 
 	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()))
+	self.Trie.Delete(string(stateObject.Address()))
 
 	delete(self.stateObjects, string(stateObject.Address()))
 }
@@ -79,7 +79,7 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
 		return stateObject
 	}
 
-	data := self.trie.Get(string(addr))
+	data := self.Trie.Get(string(addr))
 	if len(data) == 0 {
 		return nil
 	}
@@ -122,12 +122,12 @@ func (self *State) GetAccount(addr []byte) *StateObject {
 //
 
 func (s *State) Cmp(other *State) bool {
-	return s.trie.Cmp(other.trie)
+	return s.Trie.Cmp(other.Trie)
 }
 
 func (self *State) Copy() *State {
-	if self.trie != nil {
-		state := NewState(self.trie.Copy())
+	if self.Trie != nil {
+		state := NewState(self.Trie.Copy())
 		for k, stateObject := range self.stateObjects {
 			state.stateObjects[k] = stateObject.Copy()
 		}
@@ -143,21 +143,21 @@ func (self *State) Set(state *State) {
 		panic("Tried setting 'state' to nil through 'Set'")
 	}
 
-	self.trie = state.trie
+	self.Trie = state.Trie
 	self.stateObjects = state.stateObjects
 }
 
 func (s *State) Root() interface{} {
-	return s.trie.Root
+	return s.Trie.Root
 }
 
 // Resets the trie and all siblings
 func (s *State) Reset() {
-	s.trie.Undo()
+	s.Trie.Undo()
 
 	// Reset all nested states
 	for _, stateObject := range s.stateObjects {
-		if stateObject.state == nil {
+		if stateObject.State == nil {
 			continue
 		}
 
@@ -174,14 +174,14 @@ func (s *State) Sync() {
 	for _, stateObject := range s.stateObjects {
 		//s.UpdateStateObject(stateObject)
 
-		if stateObject.state == nil {
+		if stateObject.State == nil {
 			continue
 		}
 
-		stateObject.state.Sync()
+		stateObject.State.Sync()
 	}
 
-	s.trie.Sync()
+	s.Trie.Sync()
 
 	s.Empty()
 }
@@ -202,11 +202,11 @@ func (self *State) Update() {
 	}
 
 	// FIXME trie delete is broken
-	valid, t2 := ethtrie.ParanoiaCheck(self.trie)
+	valid, t2 := ethtrie.ParanoiaCheck(self.Trie)
 	if !valid {
-		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root)
+		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.Trie.Root, t2.Root)
 
-		self.trie = t2
+		self.Trie = t2
 	}
 }
 
@@ -230,8 +230,8 @@ type Manifest struct {
 	objectAddresses  map[string]bool
 	storageAddresses map[string]map[string]bool
 
-	objectChanges  map[string]*StateObject
-	storageChanges map[string]map[string]*big.Int
+	ObjectChanges  map[string]*StateObject
+	StorageChanges map[string]map[string]*big.Int
 }
 
 func NewManifest() *Manifest {
@@ -242,18 +242,18 @@ func NewManifest() *Manifest {
 }
 
 func (m *Manifest) Reset() {
-	m.objectChanges = make(map[string]*StateObject)
-	m.storageChanges = make(map[string]map[string]*big.Int)
+	m.ObjectChanges = make(map[string]*StateObject)
+	m.StorageChanges = make(map[string]map[string]*big.Int)
 }
 
 func (m *Manifest) AddObjectChange(stateObject *StateObject) {
-	m.objectChanges[string(stateObject.Address())] = stateObject
+	m.ObjectChanges[string(stateObject.Address())] = stateObject
 }
 
 func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
-	if m.storageChanges[string(stateObject.Address())] == nil {
-		m.storageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
+	if m.StorageChanges[string(stateObject.Address())] == nil {
+		m.StorageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
 	}
 
-	m.storageChanges[string(stateObject.Address())][string(storageAddr)] = storage
+	m.StorageChanges[string(stateObject.Address())][string(storageAddr)] = storage
 }
-- 
cgit v1.2.3