github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/core/state/statedb.go (about) 1 // Copyright 2014 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum 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 "fmt" 22 "math/big" 23 "sort" 24 "sync" 25 26 "github.com/SmartMeshFoundation/Spectrum/common" 27 "github.com/SmartMeshFoundation/Spectrum/core/types" 28 "github.com/SmartMeshFoundation/Spectrum/crypto" 29 "github.com/SmartMeshFoundation/Spectrum/log" 30 "github.com/SmartMeshFoundation/Spectrum/rlp" 31 "github.com/SmartMeshFoundation/Spectrum/trie" 32 ) 33 34 type revision struct { 35 id int 36 journalIndex int 37 } 38 39 type StateDB struct { 40 db Database 41 trie Trie 42 43 // This map holds 'live' objects, which will get modified while processing a state transition. 44 stateObjects map[common.Address]*stateObject 45 stateObjectsDirty map[common.Address]struct{} 46 47 // DB error. 48 // State objects are used by the consensus core and VM which are 49 // unable to deal with database-level errors. Any error that occurs 50 // during a database read is memoized here and will eventually be returned 51 // by StateDB.Commit. 52 dbErr error 53 54 // The refund counter, also used by state transitioning. 55 refund uint64 56 57 thash, bhash common.Hash 58 txIndex int 59 logs map[common.Hash][]*types.Log 60 logSize uint 61 62 preimages map[common.Hash][]byte 63 64 // Journal of state modifications. This is the backbone of 65 // Snapshot and RevertToSnapshot. 66 journal journal 67 validRevisions []revision 68 nextRevisionId int 69 70 lock sync.Mutex 71 } 72 73 // Create a new state from a given trie 74 func New(root common.Hash, db Database) (*StateDB, error) { 75 tr, err := db.OpenTrie(root) 76 if err != nil { 77 return nil, err 78 } 79 return &StateDB{ 80 db: db, 81 trie: tr, 82 stateObjects: make(map[common.Address]*stateObject), 83 stateObjectsDirty: make(map[common.Address]struct{}), 84 logs: make(map[common.Hash][]*types.Log), 85 preimages: make(map[common.Hash][]byte), 86 }, nil 87 } 88 89 // setError remembers the first non-nil error it is called with. 90 func (self *StateDB) setError(err error) { 91 if self.dbErr == nil { 92 self.dbErr = err 93 } 94 } 95 96 func (self *StateDB) Error() error { 97 return self.dbErr 98 } 99 100 // Reset clears out all emphemeral state objects from the state db, but keeps 101 // the underlying state trie to avoid reloading data for the next operations. 102 func (self *StateDB) Reset(root common.Hash) error { 103 tr, err := self.db.OpenTrie(root) 104 if err != nil { 105 return err 106 } 107 self.trie = tr 108 self.stateObjects = make(map[common.Address]*stateObject) 109 self.stateObjectsDirty = make(map[common.Address]struct{}) 110 self.thash = common.Hash{} 111 self.bhash = common.Hash{} 112 self.txIndex = 0 113 self.logs = make(map[common.Hash][]*types.Log) 114 self.logSize = 0 115 self.preimages = make(map[common.Hash][]byte) 116 self.clearJournalAndRefund() 117 return nil 118 } 119 120 func (self *StateDB) AddLog(log *types.Log) { 121 self.journal = append(self.journal, addLogChange{txhash: self.thash}) 122 123 log.TxHash = self.thash 124 log.BlockHash = self.bhash 125 log.TxIndex = uint(self.txIndex) 126 log.Index = self.logSize 127 self.logs[self.thash] = append(self.logs[self.thash], log) 128 self.logSize++ 129 } 130 131 func (self *StateDB) GetLogs(hash common.Hash) []*types.Log { 132 return self.logs[hash] 133 } 134 135 func (self *StateDB) Logs() []*types.Log { 136 var logs []*types.Log 137 for _, lgs := range self.logs { 138 logs = append(logs, lgs...) 139 } 140 return logs 141 } 142 143 // AddPreimage records a SHA3 preimage seen by the VM. 144 func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) { 145 if _, ok := self.preimages[hash]; !ok { 146 self.journal = append(self.journal, addPreimageChange{hash: hash}) 147 pi := make([]byte, len(preimage)) 148 copy(pi, preimage) 149 self.preimages[hash] = pi 150 } 151 } 152 153 // Preimages returns a list of SHA3 preimages that have been submitted. 154 func (self *StateDB) Preimages() map[common.Hash][]byte { 155 return self.preimages 156 } 157 158 // AddRefund adds gas to the refund counter 159 func (self *StateDB) AddRefund(gas uint64) { 160 self.journal = append(self.journal, refundChange{prev: self.refund}) 161 self.refund += gas 162 } 163 164 // SubRefund removes gas from the refund counter. 165 // This method will panic if the refund counter goes below zero 166 func (self *StateDB) SubRefund(gas uint64) { 167 self.journal = append(self.journal, refundChange{prev: self.refund}) 168 if gas > self.refund { 169 panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, self.refund)) 170 } 171 self.refund -= gas 172 } 173 174 // Exist reports whether the given account address exists in the state. 175 // Notably this also returns true for suicided accounts. 176 func (self *StateDB) Exist(addr common.Address) bool { 177 return self.getStateObject(addr) != nil 178 } 179 180 // Empty returns whether the state object is either non-existent 181 // or empty according to the EIP161 specification (balance = nonce = code = 0) 182 func (self *StateDB) Empty(addr common.Address) bool { 183 so := self.getStateObject(addr) 184 return so == nil || so.empty() 185 } 186 187 // Retrieve the balance from the given address or 0 if object not found 188 func (self *StateDB) GetBalance(addr common.Address) *big.Int { 189 stateObject := self.getStateObject(addr) 190 if stateObject != nil { 191 return stateObject.Balance() 192 } 193 return common.Big0 194 } 195 196 func (self *StateDB) GetNonce(addr common.Address) uint64 { 197 stateObject := self.getStateObject(addr) 198 if stateObject != nil { 199 return stateObject.Nonce() 200 } 201 202 return 0 203 } 204 205 func (self *StateDB) GetCode(addr common.Address) []byte { 206 stateObject := self.getStateObject(addr) 207 if stateObject != nil { 208 return stateObject.Code(self.db) 209 } 210 return nil 211 } 212 213 func (self *StateDB) GetCodeSize(addr common.Address) int { 214 stateObject := self.getStateObject(addr) 215 if stateObject == nil { 216 return 0 217 } 218 if stateObject.code != nil { 219 return len(stateObject.code) 220 } 221 size, err := self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash())) 222 if err != nil { 223 self.setError(err) 224 } 225 return size 226 } 227 228 func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { 229 stateObject := self.getStateObject(addr) 230 if stateObject == nil { 231 return common.Hash{} 232 } 233 return common.BytesToHash(stateObject.CodeHash()) 234 } 235 236 func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { 237 stateObject := self.getStateObject(a) 238 if stateObject != nil { 239 return stateObject.GetState(self.db, b) 240 } 241 return common.Hash{} 242 } 243 244 // StorageTrie returns the storage trie of an account. 245 // The return value is a copy and is nil for non-existent accounts. 246 func (self *StateDB) StorageTrie(a common.Address) Trie { 247 stateObject := self.getStateObject(a) 248 if stateObject == nil { 249 return nil 250 } 251 cpy := stateObject.deepCopy(self, nil) 252 return cpy.updateTrie(self.db) 253 } 254 255 func (self *StateDB) HasSuicided(addr common.Address) bool { 256 stateObject := self.getStateObject(addr) 257 if stateObject != nil { 258 return stateObject.suicided 259 } 260 return false 261 } 262 263 /* 264 * SETTERS 265 */ 266 267 // AddBalance adds amount to the account associated with addr 268 func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { 269 stateObject := self.GetOrNewStateObject(addr) 270 if stateObject != nil { 271 stateObject.AddBalance(amount) 272 } 273 } 274 275 // SubBalance subtracts amount from the account associated with addr 276 func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { 277 stateObject := self.GetOrNewStateObject(addr) 278 if stateObject != nil { 279 stateObject.SubBalance(amount) 280 } 281 } 282 283 func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) { 284 stateObject := self.GetOrNewStateObject(addr) 285 if stateObject != nil { 286 stateObject.SetBalance(amount) 287 } 288 } 289 290 func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { 291 stateObject := self.GetOrNewStateObject(addr) 292 if stateObject != nil { 293 stateObject.SetNonce(nonce) 294 } 295 } 296 297 func (self *StateDB) SetCode(addr common.Address, code []byte) { 298 stateObject := self.GetOrNewStateObject(addr) 299 if stateObject != nil { 300 stateObject.SetCode(crypto.Keccak256Hash(code), code) 301 } 302 } 303 304 func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { 305 stateObject := self.GetOrNewStateObject(addr) 306 if stateObject != nil { 307 stateObject.SetState(self.db, key, value) 308 } 309 } 310 311 // Suicide marks the given account as suicided. 312 // This clears the account balance. 313 // 314 // The account's state object is still available until the state is committed, 315 // getStateObject will return a non-nil account after Suicide. 316 func (self *StateDB) Suicide(addr common.Address) bool { 317 stateObject := self.getStateObject(addr) 318 if stateObject == nil { 319 return false 320 } 321 self.journal = append(self.journal, suicideChange{ 322 account: &addr, 323 prev: stateObject.suicided, 324 prevbalance: new(big.Int).Set(stateObject.Balance()), 325 }) 326 stateObject.markSuicided() 327 stateObject.data.Balance = new(big.Int) 328 329 return true 330 } 331 332 // 333 // Setting, updating & deleting state object methods 334 // 335 336 // updateStateObject writes the given object to the trie. 337 func (self *StateDB) updateStateObject(stateObject *stateObject) { 338 addr := stateObject.Address() 339 data, err := rlp.EncodeToBytes(stateObject) 340 if err != nil { 341 panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) 342 } 343 self.setError(self.trie.TryUpdate(addr[:], data)) 344 } 345 346 // deleteStateObject removes the given object from the state trie. 347 func (self *StateDB) deleteStateObject(stateObject *stateObject) { 348 stateObject.deleted = true 349 addr := stateObject.Address() 350 self.setError(self.trie.TryDelete(addr[:])) 351 } 352 353 // Retrieve a state object given my the address. Returns nil if not found. 354 func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { 355 // Prefer 'live' objects. 356 if obj := self.stateObjects[addr]; obj != nil { 357 if obj.deleted { 358 return nil 359 } 360 return obj 361 } 362 363 // Load the object from the database. 364 enc, err := self.trie.TryGet(addr[:]) 365 if len(enc) == 0 { 366 self.setError(err) 367 return nil 368 } 369 var data Account 370 if err := rlp.DecodeBytes(enc, &data); err != nil { 371 log.Error("Failed to decode state object", "addr", addr, "err", err) 372 return nil 373 } 374 // Insert into the live set. 375 obj := newObject(self, addr, data, self.MarkStateObjectDirty) 376 self.setStateObject(obj) 377 return obj 378 } 379 380 func (self *StateDB) setStateObject(object *stateObject) { 381 self.stateObjects[object.Address()] = object 382 } 383 384 // Retrieve a state object or create a new state object if nil 385 func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { 386 stateObject := self.getStateObject(addr) 387 if stateObject == nil || stateObject.deleted { 388 stateObject, _ = self.createObject(addr) 389 } 390 return stateObject 391 } 392 393 // MarkStateObjectDirty adds the specified object to the dirty map to avoid costly 394 // state object cache iteration to find a handful of modified ones. 395 func (self *StateDB) MarkStateObjectDirty(addr common.Address) { 396 self.stateObjectsDirty[addr] = struct{}{} 397 } 398 399 // createObject creates a new state object. If there is an existing account with 400 // the given address, it is overwritten and returned as the second return value. 401 func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { 402 prev = self.getStateObject(addr) 403 newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty) 404 newobj.setNonce(0) // sets the object to dirty 405 if prev == nil { 406 self.journal = append(self.journal, createObjectChange{account: &addr}) 407 } else { 408 self.journal = append(self.journal, resetObjectChange{prev: prev}) 409 } 410 self.setStateObject(newobj) 411 return newobj, prev 412 } 413 414 // CreateAccount explicitly creates a state object. If a state object with the address 415 // already exists the balance is carried over to the new account. 416 // 417 // CreateAccount is called during the EVM CREATE operation. The situation might arise that 418 // a contract does the following: 419 // 420 // 1. sends funds to sha(account ++ (nonce + 1)) 421 // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) 422 // 423 // Carrying over the balance ensures that Ether doesn't disappear. 424 func (self *StateDB) CreateAccount(addr common.Address) { 425 new, prev := self.createObject(addr) 426 if prev != nil { 427 new.setBalance(prev.data.Balance) 428 } 429 } 430 431 func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) { 432 so := db.getStateObject(addr) 433 if so == nil { 434 return 435 } 436 437 // When iterating over the storage check the cache first 438 for h, value := range so.cachedStorage { 439 cb(h, value) 440 } 441 442 it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil)) 443 for it.Next() { 444 // ignore cached values 445 key := common.BytesToHash(db.trie.GetKey(it.Key)) 446 if _, ok := so.cachedStorage[key]; !ok { 447 cb(key, common.BytesToHash(it.Value)) 448 } 449 } 450 } 451 452 // Copy creates a deep, independent copy of the state. 453 // Snapshots of the copied state cannot be applied to the copy. 454 func (self *StateDB) Copy() *StateDB { 455 self.lock.Lock() 456 defer self.lock.Unlock() 457 458 // Copy all the basic fields, initialize the memory ones 459 state := &StateDB{ 460 db: self.db, 461 trie: self.db.CopyTrie(self.trie), 462 stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)), 463 stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)), 464 refund: self.refund, 465 logs: make(map[common.Hash][]*types.Log, len(self.logs)), 466 logSize: self.logSize, 467 preimages: make(map[common.Hash][]byte), 468 } 469 // Copy the dirty states, logs, and preimages 470 for addr := range self.stateObjectsDirty { 471 state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty) 472 state.stateObjectsDirty[addr] = struct{}{} 473 } 474 for hash, logs := range self.logs { 475 state.logs[hash] = make([]*types.Log, len(logs)) 476 copy(state.logs[hash], logs) 477 } 478 for hash, preimage := range self.preimages { 479 state.preimages[hash] = preimage 480 } 481 return state 482 } 483 484 // Snapshot returns an identifier for the current revision of the state. 485 func (self *StateDB) Snapshot() int { 486 id := self.nextRevisionId 487 self.nextRevisionId++ 488 self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)}) 489 return id 490 } 491 492 // RevertToSnapshot reverts all state changes made since the given revision. 493 func (self *StateDB) RevertToSnapshot(revid int) { 494 // Find the snapshot in the stack of valid snapshots. 495 idx := sort.Search(len(self.validRevisions), func(i int) bool { 496 return self.validRevisions[i].id >= revid 497 }) 498 if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid { 499 panic(fmt.Errorf("revision id %v cannot be reverted", revid)) 500 } 501 snapshot := self.validRevisions[idx].journalIndex 502 503 // Replay the journal to undo changes. 504 for i := len(self.journal) - 1; i >= snapshot; i-- { 505 self.journal[i].undo(self) 506 } 507 self.journal = self.journal[:snapshot] 508 509 // Remove invalidated snapshots from the stack. 510 self.validRevisions = self.validRevisions[:idx] 511 } 512 513 // GetRefund returns the current value of the refund counter. 514 // The return value must not be modified by the caller and will become 515 // invalid at the next call to AddRefund. 516 // GetRefund returns the current value of the refund counter. 517 func (s *StateDB) GetRefund() uint64 { 518 return s.refund 519 } 520 521 // Finalise finalises the state by removing the self destructed objects 522 // and clears the journal as well as the refunds. 523 func (s *StateDB) Finalise(deleteEmptyObjects bool) { 524 for addr := range s.stateObjectsDirty { 525 stateObject := s.stateObjects[addr] 526 if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { 527 s.deleteStateObject(stateObject) 528 } else { 529 stateObject.updateRoot(s.db) 530 s.updateStateObject(stateObject) 531 } 532 } 533 // Invalidate journal because reverting across transactions is not allowed. 534 s.clearJournalAndRefund() 535 } 536 537 // IntermediateRoot computes the current root hash of the state trie. 538 // It is called in between transactions to get the root hash that 539 // goes into transaction receipts. 540 func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { 541 s.Finalise(deleteEmptyObjects) 542 return s.trie.Hash() 543 } 544 545 // Prepare sets the current transaction hash and index and block hash which is 546 // used when the EVM emits new state logs. 547 func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { 548 self.thash = thash 549 self.bhash = bhash 550 self.txIndex = ti 551 } 552 553 // DeleteSuicides flags the suicided objects for deletion so that it 554 // won't be referenced again when called / queried up on. 555 // 556 // DeleteSuicides should not be used for consensus related updates 557 // under any circumstances. 558 func (s *StateDB) DeleteSuicides() { 559 // Reset refund so that any used-gas calculations can use this method. 560 s.clearJournalAndRefund() 561 562 for addr := range s.stateObjectsDirty { 563 stateObject := s.stateObjects[addr] 564 565 // If the object has been removed by a suicide 566 // flag the object as deleted. 567 if stateObject.suicided { 568 stateObject.deleted = true 569 } 570 delete(s.stateObjectsDirty, addr) 571 } 572 } 573 574 func (s *StateDB) clearJournalAndRefund() { 575 s.journal = nil 576 s.validRevisions = s.validRevisions[:0] 577 s.refund = 0 578 } 579 580 // CommitTo writes the state to the given database. 581 func (s *StateDB) CommitTo(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (root common.Hash, err error) { 582 defer s.clearJournalAndRefund() 583 584 // Commit objects to the trie. 585 for addr, stateObject := range s.stateObjects { 586 _, isDirty := s.stateObjectsDirty[addr] 587 switch { 588 case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): 589 // If the object has been removed, don't bother syncing it 590 // and just mark it for deletion in the trie. 591 s.deleteStateObject(stateObject) 592 case isDirty: 593 // Write any contract code associated with the state object 594 if stateObject.code != nil && stateObject.dirtyCode { 595 if err := dbw.Put(stateObject.CodeHash(), stateObject.code); err != nil { 596 return common.Hash{}, err 597 } 598 stateObject.dirtyCode = false 599 } 600 // Write any storage changes in the state object to its storage trie. 601 if err := stateObject.CommitTrie(s.db, dbw); err != nil { 602 return common.Hash{}, err 603 } 604 // Update the object in the main account trie. 605 s.updateStateObject(stateObject) 606 } 607 delete(s.stateObjectsDirty, addr) 608 } 609 // Write trie changes. 610 root, err = s.trie.CommitTo(dbw) 611 log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads()) 612 return root, err 613 }