github.com/klaytn/klaytn@v1.10.2/blockchain/state/state_object.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/state/state_object.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package state 22 23 import ( 24 "bytes" 25 "errors" 26 "fmt" 27 "io" 28 "math/big" 29 "sync/atomic" 30 "time" 31 32 "github.com/klaytn/klaytn/blockchain/types/account" 33 "github.com/klaytn/klaytn/blockchain/types/accountkey" 34 "github.com/klaytn/klaytn/common" 35 "github.com/klaytn/klaytn/crypto" 36 "github.com/klaytn/klaytn/kerrors" 37 "github.com/klaytn/klaytn/rlp" 38 ) 39 40 var emptyCodeHash = crypto.Keccak256(nil) 41 42 var errAccountDoesNotExist = errors.New("account does not exist") 43 44 type Code []byte 45 46 func (self Code) String() string { 47 return string(self) // strings.Join(Disassemble(self), " ") 48 } 49 50 type Storage map[common.Hash]common.Hash 51 52 func (self Storage) String() (str string) { 53 for key, value := range self { 54 str += fmt.Sprintf("%X : %X\n", key, value) 55 } 56 57 return 58 } 59 60 func (self Storage) Copy() Storage { 61 cpy := make(Storage) 62 for key, value := range self { 63 cpy[key] = value 64 } 65 66 return cpy 67 } 68 69 // stateObject represents a Klaytn account which is being modified. 70 // 71 // The usage pattern is as follows: 72 // First you need to obtain a state object. 73 // Account values can be accessed and modified through the object. 74 // Finally, call CommitStorageTrie to write the modified storage trie into a database. 75 type stateObject struct { 76 address common.Address 77 addrHash common.Hash // hash of the address of the account 78 account account.Account 79 db *StateDB 80 81 // DB error. 82 // State objects are used by the consensus core and VM which are 83 // unable to deal with database-level errors. Any error that occurs 84 // during a database read is memoized here and will eventually be returned 85 // by StateDB.Commit. 86 dbErr error 87 88 // Write caches. 89 storageTrie Trie // storage trie, which becomes non-nil on first access 90 code Code // contract bytecode, which gets set when code is loaded 91 92 originStorage Storage // Storage cache of original entries to dedup rewrites 93 dirtyStorage Storage // Storage entries that need to be flushed to disk 94 fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. 95 96 // Cache flags. 97 // When an object is marked suicided it will be delete from the trie 98 // during the "update" phase of the state transition. 99 dirtyCode bool // true if the code was updated 100 suicided bool 101 deleted bool 102 103 encoded atomic.Value // RLP-encoded data 104 } 105 106 type encodedData struct { 107 err error // RLP-encoding error from stateObjectEncoder 108 data []byte // RLP-encoded stateObject 109 trieHashKey []byte // hash of key used to update trie 110 trieHexKey []byte // hex string of tireHashKey 111 } 112 113 // empty returns whether the account is considered empty. 114 func (s *stateObject) empty() bool { 115 return s.account.Empty() 116 } 117 118 // newObject creates a state object. 119 func newObject(db *StateDB, address common.Address, data account.Account) *stateObject { 120 return &stateObject{ 121 db: db, 122 address: address, 123 addrHash: crypto.Keccak256Hash(address[:]), 124 account: data, 125 originStorage: make(Storage), 126 dirtyStorage: make(Storage), 127 } 128 } 129 130 // EncodeRLP implements rlp.Encoder. 131 func (c *stateObject) EncodeRLP(w io.Writer) error { 132 serializer := account.NewAccountSerializerWithAccount(c.account) 133 return rlp.Encode(w, serializer) 134 } 135 136 // setError remembers the first non-nil error it is called with. 137 func (self *stateObject) setError(err error) { 138 if self.dbErr == nil { 139 self.dbErr = err 140 } 141 } 142 143 func (self *stateObject) markSuicided() { 144 self.suicided = true 145 } 146 147 func (c *stateObject) touch() { 148 c.db.journal.append(touchChange{ 149 account: &c.address, 150 }) 151 if c.address == ripemd { 152 // Explicitly put it in the dirty-cache, which is otherwise generated from 153 // flattened journals. 154 c.db.journal.dirty(c.address) 155 } 156 } 157 158 func (c *stateObject) openStorageTrie(hash common.Hash, db Database) (Trie, error) { 159 if c.db.prefetching { 160 return db.OpenStorageTrieForPrefetching(hash) 161 } 162 return db.OpenStorageTrie(hash) 163 } 164 165 func (c *stateObject) getStorageTrie(db Database) Trie { 166 if c.storageTrie == nil { 167 if acc := account.GetProgramAccount(c.account); acc != nil { 168 var err error 169 c.storageTrie, err = c.openStorageTrie(acc.GetStorageRoot(), db) 170 if err != nil { 171 c.storageTrie, _ = c.openStorageTrie(common.Hash{}, db) 172 c.setError(fmt.Errorf("can't create storage trie: %v", err)) 173 } 174 } else { 175 // not a contract account, just returns the empty trie. 176 c.storageTrie, _ = c.openStorageTrie(common.Hash{}, db) 177 } 178 } 179 return c.storageTrie 180 } 181 182 // GetState retrieves a value from the account storage trie. 183 func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { 184 // If we have a dirty value for this state entry, return it 185 value, dirty := self.dirtyStorage[key] 186 if dirty { 187 return value 188 } 189 // Otherwise return the entry's original value 190 return self.GetCommittedState(db, key) 191 } 192 193 // GetCommittedState retrieves a value from the committed account storage trie. 194 func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 195 // If we have the original value cached, return that 196 value, cached := self.originStorage[key] 197 if cached { 198 return value 199 } 200 // Track the amount of time wasted on reading the storage trie 201 var ( 202 enc []byte 203 err error 204 meter *time.Duration 205 ) 206 readStart := time.Now() 207 if EnabledExpensive { 208 // If the snap is 'under construction', the first lookup may fail. If that 209 // happens, we don't want to double-count the time elapsed. Thus this 210 // dance with the metering. 211 defer func(start time.Time) { 212 if meter != nil { 213 *meter += time.Since(readStart) 214 } 215 }(time.Now()) 216 } 217 if self.db.snap != nil { 218 if EnabledExpensive { 219 meter = &self.db.SnapshotStorageReads 220 } 221 // If the object was destructed in *this* block (and potentially resurrected), 222 // the storage has been cleared out, and we should *not* consult the previous 223 // snapshot about any storage values. The only possible alternatives are: 224 // 1) resurrect happened, and new slot values were set -- those should 225 // have been handles via pendingStorage above. 226 // 2) we don't have new values, and can deliver empty response back 227 if _, destructed := self.db.snapDestructs[self.addrHash]; destructed { 228 return common.Hash{} 229 } 230 enc, err = self.db.snap.Storage(self.addrHash, crypto.Keccak256Hash(key.Bytes())) 231 } 232 // If the snapshot is unavailable or reading from it fails, load from the database. 233 if self.db.snap == nil || err != nil { 234 if EnabledExpensive { 235 if meter != nil { 236 // If we already spent time checking the snapshot, account for it 237 // and reset the readStart 238 *meter += time.Since(readStart) 239 readStart = time.Now() 240 } 241 meter = &self.db.StorageReads 242 } 243 // Load from DB in case it is missing. 244 if enc, err = self.getStorageTrie(db).TryGet(key[:]); err != nil { 245 self.setError(err) 246 return common.Hash{} 247 } 248 } 249 if len(enc) > 0 { 250 _, content, _, err := rlp.Split(enc) 251 if err != nil { 252 self.setError(err) 253 } 254 value.SetBytes(content) 255 } 256 self.originStorage[key] = value 257 return value 258 } 259 260 // SetState updates a value in account trie. 261 func (self *stateObject) SetState(db Database, key, value common.Hash) { 262 // If the new value is the same as old, don't set 263 prev := self.GetState(db, key) 264 if prev == value { 265 return 266 } 267 // New value is different, update and journal the change 268 self.db.journal.append(storageChange{ 269 account: &self.address, 270 key: key, 271 prevalue: prev, 272 }) 273 self.setState(key, value) 274 } 275 276 // SetStorage replaces the entire state storage with the given one. 277 // 278 // After this function is called, all original state will be ignored and state 279 // lookup only happens in the fake state storage. 280 // 281 // Note this function should only be used for debugging purpose. 282 func (self *stateObject) SetStorage(storage map[common.Hash]common.Hash) { 283 // Allocate fake storage if it's nil. 284 if self.fakeStorage == nil { 285 self.fakeStorage = make(Storage) 286 } 287 for key, value := range storage { 288 self.fakeStorage[key] = value 289 } 290 // Don't bother journal since this function should only be used for 291 // debugging and the `fake` storage won't be committed to database. 292 } 293 294 // IsContractAccount returns true is the account has a non-empty codeHash. 295 func (self *stateObject) IsContractAccount() bool { 296 acc := account.GetProgramAccount(self.account) 297 if acc != nil && !bytes.Equal(acc.GetCodeHash(), emptyCodeHash) { 298 return true 299 } 300 return false 301 } 302 303 // IsContractAvailable returns true if the account has a smart contract code hash and didn't self-destruct 304 func (self *stateObject) IsContractAvailable() bool { 305 acc := account.GetProgramAccount(self.account) 306 if acc != nil && !bytes.Equal(acc.GetCodeHash(), emptyCodeHash) && self.suicided == false { 307 return true 308 } 309 return false 310 } 311 312 // IsProgramAccount returns true if the account implements ProgramAccount. 313 func (self *stateObject) IsProgramAccount() bool { 314 return account.GetProgramAccount(self.account) != nil 315 } 316 317 func (self *stateObject) GetKey() accountkey.AccountKey { 318 if ak := account.GetAccountWithKey(self.account); ak != nil { 319 return ak.GetKey() 320 } 321 return accountkey.NewAccountKeyLegacy() 322 } 323 324 func (self *stateObject) setState(key, value common.Hash) { 325 self.dirtyStorage[key] = value 326 } 327 328 func (self *stateObject) UpdateKey(newKey accountkey.AccountKey, currentBlockNumber uint64) error { 329 return self.account.UpdateKey(newKey, currentBlockNumber) 330 } 331 332 // updateStorageTrie writes cached storage modifications into the object's storage trie. 333 func (self *stateObject) updateStorageTrie(db Database) Trie { 334 // Track the amount of time wasted on updating the storage trie 335 if EnabledExpensive { 336 defer func(start time.Time) { self.db.StorageUpdates += time.Since(start) }(time.Now()) 337 } 338 // The snapshot storage map for the object 339 var storage map[common.Hash][]byte 340 // Insert all the pending updates into the trie 341 tr := self.getStorageTrie(db) 342 for key, value := range self.dirtyStorage { 343 delete(self.dirtyStorage, key) 344 345 // Skip noop changes, persist actual changes 346 if value == self.originStorage[key] { 347 continue 348 } 349 self.originStorage[key] = value 350 351 var v []byte 352 if (value == common.Hash{}) { 353 self.setError(tr.TryDelete(key[:])) 354 } else { 355 // Encoding []byte cannot fail, ok to ignore the error. 356 v, _ = rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 357 self.setError(tr.TryUpdate(key[:], v)) 358 } 359 // If state snapshotting is active, cache the data til commit 360 if self.db.snap != nil { 361 if storage == nil { 362 // Retrieve the old storage map, if available, create a new one otherwise 363 if storage = self.db.snapStorage[self.addrHash]; storage == nil { 364 storage = make(map[common.Hash][]byte) 365 self.db.snapStorage[self.addrHash] = storage 366 } 367 } 368 storage[crypto.Keccak256Hash(key[:])] = v // v will be nil if it's deleted 369 } 370 } 371 return tr 372 } 373 374 // updateStorageRoot sets the storage trie root to the newly updated one. 375 func (self *stateObject) updateStorageRoot(db Database) { 376 if acc := account.GetProgramAccount(self.account); acc != nil { 377 // Track the amount of time wasted on hashing the storage trie 378 if EnabledExpensive { 379 defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now()) 380 } 381 acc.SetStorageRoot(self.storageTrie.Hash()) 382 } 383 } 384 385 // setStorageRoot calls SetStorageRoot if updateStorageRoot flag is given true. 386 // Otherwise, it just marks the object and update their root hash later. 387 func (self *stateObject) setStorageRoot(updateStorageRoot bool, objectsToUpdate map[common.Address]struct{}) { 388 if acc := account.GetProgramAccount(self.account); acc != nil { 389 if updateStorageRoot { 390 // Track the amount of time wasted on hashing the storage trie 391 if EnabledExpensive { 392 defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now()) 393 } 394 acc.SetStorageRoot(self.storageTrie.Hash()) 395 return 396 } 397 // If updateStorageRoot == false, it just marks the object and updates its storage root later. 398 objectsToUpdate[self.Address()] = struct{}{} 399 } 400 } 401 402 // CommitStorageTrie writes the storage trie of the object to db. 403 // This updates the storage trie root. 404 func (self *stateObject) CommitStorageTrie(db Database) error { 405 self.updateStorageTrie(db) 406 if self.dbErr != nil { 407 return self.dbErr 408 } 409 // Track the amount of time wasted on committing the storage trie 410 if EnabledExpensive { 411 defer func(start time.Time) { self.db.StorageCommits += time.Since(start) }(time.Now()) 412 } 413 if acc := account.GetProgramAccount(self.account); acc != nil { 414 root, err := self.storageTrie.Commit(nil) 415 if err != nil { 416 return err 417 } 418 acc.SetStorageRoot(root) 419 } 420 return nil 421 } 422 423 // AddBalance removes amount from c's balance. 424 // It is used to add funds to the destination account of a transfer. 425 func (c *stateObject) AddBalance(amount *big.Int) { 426 // EIP158: We must check emptiness for the objects such that the account 427 // clearing (0,0,0 objects) can take effect. 428 if amount.Sign() == 0 { 429 if c.empty() { 430 c.touch() 431 } 432 433 return 434 } 435 c.SetBalance(new(big.Int).Add(c.Balance(), amount)) 436 } 437 438 // SubBalance removes amount from c's balance. 439 // It is used to remove funds from the origin account of a transfer. 440 func (c *stateObject) SubBalance(amount *big.Int) { 441 if amount.Sign() == 0 { 442 return 443 } 444 c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) 445 } 446 447 func (self *stateObject) SetBalance(amount *big.Int) { 448 self.db.journal.append(balanceChange{ 449 account: &self.address, 450 prev: new(big.Int).Set(self.account.GetBalance()), 451 }) 452 self.setBalance(amount) 453 } 454 455 func (self *stateObject) setBalance(amount *big.Int) { 456 self.account.SetBalance(amount) 457 } 458 459 // Return the gas back to the origin. Used by the Virtual machine or Closures 460 func (c *stateObject) ReturnGas(gas *big.Int) {} 461 462 func (self *stateObject) deepCopy(db *StateDB) *stateObject { 463 stateObject := newObject(db, self.address, self.account.DeepCopy()) 464 if self.storageTrie != nil { 465 stateObject.storageTrie = db.db.CopyTrie(self.storageTrie) 466 } 467 stateObject.code = self.code 468 stateObject.dirtyStorage = self.dirtyStorage.Copy() 469 stateObject.originStorage = self.originStorage.Copy() 470 stateObject.suicided = self.suicided 471 stateObject.dirtyCode = self.dirtyCode 472 stateObject.deleted = self.deleted 473 return stateObject 474 } 475 476 // 477 // Attribute accessors 478 // 479 480 // Returns the address of the contract/account 481 func (c *stateObject) Address() common.Address { 482 return c.address 483 } 484 485 // Code returns the contract code associated with this object, if any. 486 func (self *stateObject) Code(db Database) []byte { 487 if self.code != nil { 488 return self.code 489 } 490 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 491 return nil 492 } 493 code, err := db.ContractCode(common.BytesToHash(self.CodeHash())) 494 if err != nil { 495 self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) 496 } 497 self.code = code 498 return code 499 } 500 501 // CodeSize returns the size of the contract code associated with this object, 502 // or zero if none. This method is an almost mirror of Code, but uses a cache 503 // inside the database to avoid loading codes seen recently. 504 func (self *stateObject) CodeSize(db Database) int { 505 if self.code != nil { 506 return len(self.code) 507 } 508 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 509 return 0 510 } 511 size, err := db.ContractCodeSize(common.BytesToHash(self.CodeHash())) 512 if err != nil { 513 self.setError(fmt.Errorf("can't load code size %x: %v", self.CodeHash(), err)) 514 } 515 return size 516 } 517 518 func (self *stateObject) SetCode(codeHash common.Hash, code []byte) error { 519 prevcode := self.Code(self.db.db) 520 self.db.journal.append(codeChange{ 521 account: &self.address, 522 prevhash: self.CodeHash(), 523 prevcode: prevcode, 524 }) 525 return self.setCode(codeHash, code) 526 } 527 528 func (self *stateObject) setCode(codeHash common.Hash, code []byte) error { 529 acc := account.GetProgramAccount(self.account) 530 if acc == nil { 531 logger.Error("setCode() should be called only to a ProgramAccount!", "account address", self.address) 532 return kerrors.ErrNotProgramAccount 533 } 534 self.code = code 535 acc.SetCodeHash(codeHash[:]) 536 self.dirtyCode = true 537 return nil 538 } 539 540 // IncNonce increases the nonce of the account by one with making a journal of the previous nonce. 541 func (self *stateObject) IncNonce() { 542 nonce := self.account.GetNonce() 543 self.db.journal.append(nonceChange{ 544 account: &self.address, 545 prev: nonce, 546 }) 547 self.setNonce(nonce + 1) 548 } 549 550 func (self *stateObject) SetNonce(nonce uint64) { 551 self.db.journal.append(nonceChange{ 552 account: &self.address, 553 prev: self.account.GetNonce(), 554 }) 555 self.setNonce(nonce) 556 } 557 558 func (self *stateObject) setNonce(nonce uint64) { 559 self.account.SetNonce(nonce) 560 } 561 562 func (self *stateObject) CodeHash() []byte { 563 if acc := account.GetProgramAccount(self.account); acc != nil { 564 return acc.GetCodeHash() 565 } 566 return emptyCodeHash 567 } 568 569 func (self *stateObject) Balance() *big.Int { 570 return self.account.GetBalance() 571 } 572 573 //func (self *stateObject) HumanReadable() bool { 574 // return self.account.GetHumanReadable() 575 //} 576 577 func (self *stateObject) Nonce() uint64 { 578 return self.account.GetNonce() 579 } 580 581 // Never called, but must be present to allow stateObject to be used 582 // as a vm.Account interface that also satisfies the vm.ContractRef 583 // interface. Interfaces are awesome. 584 func (self *stateObject) Value() *big.Int { 585 panic("Value on stateObject should never be called") 586 }