diff options
author | obscuren <geffobscura@gmail.com> | 2014-06-17 00:25:24 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-06-17 00:25:24 +0800 |
commit | 5a0e75173626704c3d58be582dff318218569ef3 (patch) | |
tree | 801ec6d33fe21e46230a3082cd069534f64aa251 /ethchain/state.go | |
parent | 006ac772e6c81271a84ff56e00527b2adbc0129c (diff) | |
parent | ff0f15f7634ca713b0ce8232a8fa63eec5c3fad7 (diff) | |
download | go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar.gz go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar.bz2 go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar.lz go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar.xz go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.tar.zst go-tangerine-5a0e75173626704c3d58be582dff318218569ef3.zip |
Merge branch 'release/0.5.13'
Diffstat (limited to 'ethchain/state.go')
-rw-r--r-- | ethchain/state.go | 173 |
1 files changed, 134 insertions, 39 deletions
diff --git a/ethchain/state.go b/ethchain/state.go index 5af748e00..9a9d0a278 100644 --- a/ethchain/state.go +++ b/ethchain/state.go @@ -16,12 +16,14 @@ type State struct { // Nested states states map[string]*State + stateObjects map[string]*StateObject + manifest *Manifest } // Create a new state from a given trie func NewState(trie *ethutil.Trie) *State { - return &State{trie: trie, states: make(map[string]*State), manifest: NewManifest()} + return &State{trie: trie, states: make(map[string]*State), stateObjects: make(map[string]*StateObject), manifest: NewManifest()} } // Resets the trie and all siblings @@ -29,16 +31,24 @@ func (s *State) Reset() { s.trie.Undo() // Reset all nested states - for _, state := range s.states { - state.Reset() + for _, stateObject := range s.stateObjects { + if stateObject.state == nil { + continue + } + + stateObject.state.Reset() } } // Syncs the trie and all siblings func (s *State) Sync() { // Sync all nested states - for _, state := range s.states { - state.Sync() + for _, stateObject := range s.stateObjects { + if stateObject.state == nil { + continue + } + + stateObject.state.Sync() } s.trie.Sync() @@ -54,62 +64,66 @@ func (s *State) EachStorage(cb ethutil.EachCallback) { it.Each(cb) } -func (s *State) GetStateObject(addr []byte) *StateObject { - data := s.trie.Get(string(addr)) - if data == "" { - return nil +func (self *State) UpdateStateObject(stateObject *StateObject) { + addr := stateObject.Address() + + if self.stateObjects[string(addr)] == nil { + self.stateObjects[string(addr)] = stateObject } - stateObject := NewStateObjectFromBytes(addr, []byte(data)) + ethutil.Config.Db.Put(ethutil.Sha3Bin(stateObject.Script()), stateObject.Script()) - // Check if there's a cached state for this contract - cachedStateObject := s.states[string(addr)] - if cachedStateObject != nil { - //fmt.Printf("get cached #%d %x addr: %x\n", cachedStateObject.trie.Cache().Len(), cachedStateObject.Root(), addr[0:4]) - stateObject.state = cachedStateObject - } + self.trie.Update(string(addr), string(stateObject.RlpEncode())) - return stateObject + self.manifest.AddObjectChange(stateObject) } -// Updates any given state object -func (s *State) UpdateStateObject(object *StateObject) { - addr := object.Address() - - if object.state != nil && s.states[string(addr)] == nil { - s.states[string(addr)] = object.state - //fmt.Printf("update cached #%d %x addr: %x\n", object.state.trie.Cache().Len(), object.state.Root(), addr[0:4]) +func (self *State) GetStateObject(addr []byte) *StateObject { + stateObject := self.stateObjects[string(addr)] + if stateObject != nil { + return stateObject } - ethutil.Config.Db.Put(ethutil.Sha3Bin(object.Script()), object.Script()) + data := self.trie.Get(string(addr)) + if len(data) == 0 { + return nil + } - s.trie.Update(string(addr), string(object.RlpEncode())) + stateObject = NewStateObjectFromBytes(addr, []byte(data)) + self.stateObjects[string(addr)] = stateObject - s.manifest.AddObjectChange(object) + return stateObject } -func (s *State) GetAccount(addr []byte) (account *StateObject) { - data := s.trie.Get(string(addr)) - if data == "" { - account = NewAccount(addr, big.NewInt(0)) - } else { - account = NewStateObjectFromBytes(addr, []byte(data)) +func (self *State) GetOrNewStateObject(addr []byte) *StateObject { + stateObject := self.GetStateObject(addr) + if stateObject == nil { + stateObject = NewStateObject(addr) + self.stateObjects[string(addr)] = stateObject } - return + return stateObject +} + +func (self *State) GetAccount(addr []byte) *StateObject { + return self.GetOrNewStateObject(addr) } func (s *State) Cmp(other *State) bool { return s.trie.Cmp(other.trie) } -func (s *State) Copy() *State { - state := NewState(s.trie.Copy()) - for k, subState := range s.states { - state.states[k] = subState.Copy() +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 state + return nil } func (s *State) Snapshot() *State { @@ -165,3 +179,84 @@ func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte m.storageChanges[string(stateObject.Address())][string(storageAddr)] = storage } + +/* + +// Resets the trie and all siblings +func (s *State) Reset() { + s.trie.Undo() + + // Reset all nested states + for _, state := range s.states { + state.Reset() + } +} + +// Syncs the trie and all siblings +func (s *State) Sync() { + // Sync all nested states + for _, state := range s.states { + state.Sync() + } + + s.trie.Sync() +} +func (s *State) GetStateObject(addr []byte) *StateObject { + data := s.trie.Get(string(addr)) + if data == "" { + return nil + } + + stateObject := NewStateObjectFromBytes(addr, []byte(data)) + + // Check if there's a cached state for this contract + cachedStateObject := s.states[string(addr)] + if cachedStateObject != nil { + //fmt.Printf("get cached #%d %x addr: %x\n", cachedStateObject.trie.Cache().Len(), cachedStateObject.Root(), addr[0:4]) + stateObject.state = cachedStateObject + } + + return stateObject +} + +// Updates any given state object +func (s *State) UpdateStateObject(object *StateObject) { + addr := object.Address() + + if object.state != nil && s.states[string(addr)] == nil { + s.states[string(addr)] = object.state + } + + ethutil.Config.Db.Put(ethutil.Sha3Bin(object.Script()), object.Script()) + + s.trie.Update(string(addr), string(object.RlpEncode())) + + s.manifest.AddObjectChange(object) +} + +func (s *State) GetAccount(addr []byte) (account *StateObject) { + data := s.trie.Get(string(addr)) + if data == "" { + account = NewAccount(addr, big.NewInt(0)) + } else { + account = NewStateObjectFromBytes(addr, []byte(data)) + } + + // Check if there's a cached state for this contract + cachedStateObject := s.states[string(addr)] + if cachedStateObject != nil { + account.state = cachedStateObject + } + + return +} + +func (s *State) Copy() *State { + state := NewState(s.trie.Copy()) + for k, subState := range s.states { + state.states[k] = subState.Copy() + } + + return state +} +*/ |