github.com/immesys/bw2bc@v1.1.0/core/state/statedb.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package state provides a caching layer atop the Ethereum state trie. 18 package state 19 20 import ( 21 "bytes" 22 "math/big" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/logger" 26 "github.com/ethereum/go-ethereum/logger/glog" 27 "github.com/ethereum/go-ethereum/trie" 28 ) 29 30 // StateDBs within the ethereum protocol are used to store anything 31 // within the merkle trie. StateDBs take care of caching and storing 32 // nested states. It's the general query interface to retrieve: 33 // * Contracts 34 // * Accounts 35 type StateDB struct { 36 db common.Database 37 trie *trie.SecureTrie 38 root common.Hash 39 40 stateObjects map[string]*StateObject 41 42 refund *big.Int 43 44 thash, bhash common.Hash 45 txIndex int 46 logs map[common.Hash]Logs 47 logSize uint 48 } 49 50 // Create a new state from a given trie 51 func New(root common.Hash, db common.Database) *StateDB { 52 trie := trie.NewSecure(root[:], db) 53 return &StateDB{root: root, db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} 54 } 55 56 func (self *StateDB) PrintRoot() { 57 self.trie.Trie.PrintRoot() 58 } 59 60 func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) { 61 self.thash = thash 62 self.bhash = bhash 63 self.txIndex = ti 64 } 65 66 func (self *StateDB) AddLog(log *Log) { 67 log.TxHash = self.thash 68 log.BlockHash = self.bhash 69 log.TxIndex = uint(self.txIndex) 70 log.Index = self.logSize 71 self.logs[self.thash] = append(self.logs[self.thash], log) 72 self.logSize++ 73 } 74 75 func (self *StateDB) GetLogs(hash common.Hash) Logs { 76 return self.logs[hash] 77 } 78 79 func (self *StateDB) Logs() Logs { 80 var logs Logs 81 for _, lgs := range self.logs { 82 logs = append(logs, lgs...) 83 } 84 return logs 85 } 86 87 func (self *StateDB) Refund(gas *big.Int) { 88 self.refund.Add(self.refund, gas) 89 } 90 91 /* 92 * GETTERS 93 */ 94 95 func (self *StateDB) HasAccount(addr common.Address) bool { 96 return self.GetStateObject(addr) != nil 97 } 98 99 // Retrieve the balance from the given address or 0 if object not found 100 func (self *StateDB) GetBalance(addr common.Address) *big.Int { 101 stateObject := self.GetStateObject(addr) 102 if stateObject != nil { 103 return stateObject.balance 104 } 105 106 return common.Big0 107 } 108 109 func (self *StateDB) GetNonce(addr common.Address) uint64 { 110 stateObject := self.GetStateObject(addr) 111 if stateObject != nil { 112 return stateObject.nonce 113 } 114 115 return 0 116 } 117 118 func (self *StateDB) GetCode(addr common.Address) []byte { 119 stateObject := self.GetStateObject(addr) 120 if stateObject != nil { 121 return stateObject.code 122 } 123 124 return nil 125 } 126 127 func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { 128 stateObject := self.GetStateObject(a) 129 if stateObject != nil { 130 return stateObject.GetState(b) 131 } 132 133 return common.Hash{} 134 } 135 136 func (self *StateDB) IsDeleted(addr common.Address) bool { 137 stateObject := self.GetStateObject(addr) 138 if stateObject != nil { 139 return stateObject.remove 140 } 141 return false 142 } 143 144 /* 145 * SETTERS 146 */ 147 148 func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { 149 stateObject := self.GetOrNewStateObject(addr) 150 if stateObject != nil { 151 stateObject.AddBalance(amount) 152 } 153 } 154 155 func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { 156 stateObject := self.GetOrNewStateObject(addr) 157 if stateObject != nil { 158 stateObject.SetNonce(nonce) 159 } 160 } 161 162 func (self *StateDB) SetCode(addr common.Address, code []byte) { 163 stateObject := self.GetOrNewStateObject(addr) 164 if stateObject != nil { 165 stateObject.SetCode(code) 166 } 167 } 168 169 func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { 170 stateObject := self.GetOrNewStateObject(addr) 171 if stateObject != nil { 172 stateObject.SetState(key, value) 173 } 174 } 175 176 func (self *StateDB) Delete(addr common.Address) bool { 177 stateObject := self.GetStateObject(addr) 178 if stateObject != nil { 179 stateObject.MarkForDeletion() 180 stateObject.balance = new(big.Int) 181 182 return true 183 } 184 185 return false 186 } 187 188 // 189 // Setting, updating & deleting state object methods 190 // 191 192 // Update the given state object and apply it to state trie 193 func (self *StateDB) UpdateStateObject(stateObject *StateObject) { 194 //addr := stateObject.Address() 195 196 if len(stateObject.CodeHash()) > 0 { 197 self.db.Put(stateObject.CodeHash(), stateObject.code) 198 } 199 200 addr := stateObject.Address() 201 self.trie.Update(addr[:], stateObject.RlpEncode()) 202 } 203 204 // Delete the given state object and delete it from the state trie 205 func (self *StateDB) DeleteStateObject(stateObject *StateObject) { 206 stateObject.deleted = true 207 208 addr := stateObject.Address() 209 self.trie.Delete(addr[:]) 210 } 211 212 // Retrieve a state object given my the address. Nil if not found 213 func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) { 214 stateObject = self.stateObjects[addr.Str()] 215 if stateObject != nil { 216 if stateObject.deleted { 217 stateObject = nil 218 } 219 220 return stateObject 221 } 222 223 data := self.trie.Get(addr[:]) 224 if len(data) == 0 { 225 return nil 226 } 227 228 stateObject = NewStateObjectFromBytes(addr, []byte(data), self.db) 229 self.SetStateObject(stateObject) 230 231 return stateObject 232 } 233 234 func (self *StateDB) SetStateObject(object *StateObject) { 235 self.stateObjects[object.Address().Str()] = object 236 } 237 238 // Retrieve a state object or create a new state object if nil 239 func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject { 240 stateObject := self.GetStateObject(addr) 241 if stateObject == nil || stateObject.deleted { 242 stateObject = self.CreateAccount(addr) 243 } 244 245 return stateObject 246 } 247 248 // NewStateObject create a state object whether it exist in the trie or not 249 func (self *StateDB) newStateObject(addr common.Address) *StateObject { 250 if glog.V(logger.Core) { 251 glog.Infof("(+) %x\n", addr) 252 } 253 254 stateObject := NewStateObject(addr, self.db) 255 self.stateObjects[addr.Str()] = stateObject 256 257 return stateObject 258 } 259 260 // Creates creates a new state object and takes ownership. This is different from "NewStateObject" 261 func (self *StateDB) CreateAccount(addr common.Address) *StateObject { 262 // Get previous (if any) 263 so := self.GetStateObject(addr) 264 // Create a new one 265 newSo := self.newStateObject(addr) 266 267 // If it existed set the balance to the new account 268 if so != nil { 269 newSo.balance = so.balance 270 } 271 272 return newSo 273 } 274 275 // 276 // Setting, copying of the state methods 277 // 278 279 func (s *StateDB) Cmp(other *StateDB) bool { 280 return bytes.Equal(s.trie.Root(), other.trie.Root()) 281 } 282 283 func (self *StateDB) Copy() *StateDB { 284 state := New(common.Hash{}, self.db) 285 state.trie = self.trie 286 for k, stateObject := range self.stateObjects { 287 state.stateObjects[k] = stateObject.Copy() 288 } 289 290 state.refund.Set(self.refund) 291 292 for hash, logs := range self.logs { 293 state.logs[hash] = make(Logs, len(logs)) 294 copy(state.logs[hash], logs) 295 } 296 state.logSize = self.logSize 297 298 return state 299 } 300 301 func (self *StateDB) Set(state *StateDB) { 302 self.trie = state.trie 303 self.stateObjects = state.stateObjects 304 305 self.refund = state.refund 306 self.logs = state.logs 307 self.logSize = state.logSize 308 } 309 310 func (s *StateDB) Root() common.Hash { 311 return common.BytesToHash(s.trie.Root()) 312 } 313 314 func (s *StateDB) Trie() *trie.SecureTrie { 315 return s.trie 316 } 317 318 // Resets the trie and all siblings 319 func (s *StateDB) Reset() { 320 s.trie.Reset() 321 322 // Reset all nested states 323 for _, stateObject := range s.stateObjects { 324 stateObject.Reset() 325 } 326 327 s.Empty() 328 } 329 330 // Syncs the trie and all siblings 331 func (s *StateDB) Sync() { 332 // Sync all nested states 333 for _, stateObject := range s.stateObjects { 334 stateObject.trie.Commit() 335 } 336 337 s.trie.Commit() 338 339 s.Empty() 340 } 341 342 func (self *StateDB) Empty() { 343 self.stateObjects = make(map[string]*StateObject) 344 self.refund = new(big.Int) 345 } 346 347 func (self *StateDB) Refunds() *big.Int { 348 return self.refund 349 } 350 351 // SyncIntermediate updates the intermediate state and all mid steps 352 func (self *StateDB) SyncIntermediate() { 353 self.refund = new(big.Int) 354 355 for _, stateObject := range self.stateObjects { 356 if stateObject.dirty { 357 if stateObject.remove { 358 self.DeleteStateObject(stateObject) 359 } else { 360 stateObject.Update() 361 362 self.UpdateStateObject(stateObject) 363 } 364 stateObject.dirty = false 365 } 366 } 367 } 368 369 // SyncObjects syncs the changed objects to the trie 370 func (self *StateDB) SyncObjects() { 371 self.trie = trie.NewSecure(self.root[:], self.db) 372 373 self.refund = new(big.Int) 374 375 for _, stateObject := range self.stateObjects { 376 if stateObject.remove { 377 self.DeleteStateObject(stateObject) 378 } else { 379 stateObject.Update() 380 381 self.UpdateStateObject(stateObject) 382 } 383 stateObject.dirty = false 384 } 385 } 386 387 // Debug stuff 388 func (self *StateDB) CreateOutputForDiff() { 389 for _, stateObject := range self.stateObjects { 390 stateObject.CreateOutputForDiff() 391 } 392 }