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