gitlab.com/flarenetwork/coreth@v0.1.1/core/state/state_object.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2014 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package state 28 29 import ( 30 "bytes" 31 "fmt" 32 "io" 33 "math/big" 34 "sync" 35 "time" 36 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/crypto" 39 "github.com/ethereum/go-ethereum/metrics" 40 "github.com/ethereum/go-ethereum/rlp" 41 ) 42 43 var emptyCodeHash = crypto.Keccak256(nil) 44 45 type Code []byte 46 47 func (c Code) String() string { 48 return string(c) //strings.Join(Disassemble(c), " ") 49 } 50 51 type Storage map[common.Hash]common.Hash 52 53 func (s Storage) String() (str string) { 54 for key, value := range s { 55 str += fmt.Sprintf("%X : %X\n", key, value) 56 } 57 58 return 59 } 60 61 func (s Storage) Copy() Storage { 62 cpy := make(Storage) 63 for key, value := range s { 64 cpy[key] = value 65 } 66 67 return cpy 68 } 69 70 // stateObject represents an Ethereum account which is being modified. 71 // 72 // The usage pattern is as follows: 73 // First you need to obtain a state object. 74 // Account values can be accessed and modified through the object. 75 // Finally, call CommitTrie to write the modified storage trie into a database. 76 type stateObject struct { 77 address common.Address 78 addrHash common.Hash // hash of ethereum address of the account 79 // dataLock protects the [data] field to prevent a race condition 80 // in the transaction pool tests. TODO remove after re-implementing 81 // tx pool to be synchronous. 82 dataLock sync.RWMutex 83 data Account 84 db *StateDB 85 86 // DB error. 87 // State objects are used by the consensus core and VM which are 88 // unable to deal with database-level errors. Any error that occurs 89 // during a database read is memoized here and will eventually be returned 90 // by StateDB.Commit. 91 dbErr error 92 93 // Write caches. 94 trie Trie // storage trie, which becomes non-nil on first access 95 code Code // contract bytecode, which gets set when code is loaded 96 97 originStorage Storage // Storage cache of original entries to dedup rewrites, reset for every transaction 98 pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block 99 dirtyStorage Storage // Storage entries that have been modified in the current transaction execution 100 fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. 101 102 // Cache flags. 103 // When an object is marked suicided it will be delete from the trie 104 // during the "update" phase of the state transition. 105 dirtyCode bool // true if the code was updated 106 suicided bool 107 deleted bool 108 } 109 110 // empty returns whether the account is considered empty. 111 func (s *stateObject) empty() bool { 112 return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) && !s.data.IsMultiCoin 113 } 114 115 // Account is the Ethereum consensus representation of accounts. 116 // These objects are stored in the main account trie. 117 type Account struct { 118 Nonce uint64 119 Balance *big.Int 120 Root common.Hash // merkle root of the storage trie 121 CodeHash []byte 122 IsMultiCoin bool 123 } 124 125 // newObject creates a state object. 126 func newObject(db *StateDB, address common.Address, data Account) *stateObject { 127 if data.Balance == nil { 128 data.Balance = new(big.Int) 129 } 130 if data.CodeHash == nil { 131 data.CodeHash = emptyCodeHash 132 } 133 if data.Root == (common.Hash{}) { 134 data.Root = emptyRoot 135 } 136 return &stateObject{ 137 db: db, 138 address: address, 139 addrHash: crypto.Keccak256Hash(address[:]), 140 data: data, 141 originStorage: make(Storage), 142 pendingStorage: make(Storage), 143 dirtyStorage: make(Storage), 144 } 145 } 146 147 // EncodeRLP implements rlp.Encoder. 148 func (s *stateObject) EncodeRLP(w io.Writer) error { 149 return rlp.Encode(w, s.data) 150 } 151 152 // setError remembers the first non-nil error it is called with. 153 func (s *stateObject) setError(err error) { 154 if s.dbErr == nil { 155 s.dbErr = err 156 } 157 } 158 159 func (s *stateObject) markSuicided() { 160 s.suicided = true 161 } 162 163 func (s *stateObject) touch() { 164 s.db.journal.append(touchChange{ 165 account: &s.address, 166 }) 167 if s.address == ripemd { 168 // Explicitly put it in the dirty-cache, which is otherwise generated from 169 // flattened journals. 170 s.db.journal.dirty(s.address) 171 } 172 } 173 174 func (s *stateObject) getTrie(db Database) Trie { 175 if s.trie == nil { 176 // Try fetching from prefetcher first 177 // We don't prefetch empty tries 178 if s.data.Root != emptyRoot && s.db.prefetcher != nil { 179 // When the miner is creating the pending state, there is no 180 // prefetcher 181 s.trie = s.db.prefetcher.trie(s.data.Root) 182 } 183 if s.trie == nil { 184 var err error 185 s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) 186 if err != nil { 187 s.trie, _ = db.OpenStorageTrie(s.addrHash, common.Hash{}) 188 s.setError(fmt.Errorf("can't create storage trie: %v", err)) 189 } 190 } 191 } 192 return s.trie 193 } 194 195 // GetState retrieves a value from the account storage trie. 196 func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { 197 // If the fake storage is set, only lookup the state here(in the debugging mode) 198 if s.fakeStorage != nil { 199 return s.fakeStorage[key] 200 } 201 // If we have a dirty value for this state entry, return it 202 value, dirty := s.dirtyStorage[key] 203 if dirty { 204 return value 205 } 206 // Otherwise return the entry's original value 207 return s.GetCommittedState(db, key) 208 } 209 210 // GetCommittedState retrieves a value from the committed account storage trie. 211 func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 212 // If the fake storage is set, only lookup the state here(in the debugging mode) 213 if s.fakeStorage != nil { 214 return s.fakeStorage[key] 215 } 216 // If we have a pending write or clean cached, return that 217 if value, pending := s.pendingStorage[key]; pending { 218 return value 219 } 220 if value, cached := s.originStorage[key]; cached { 221 return value 222 } 223 // If no live objects are available, attempt to use snapshots 224 var ( 225 enc []byte 226 err error 227 meter *time.Duration 228 ) 229 readStart := time.Now() 230 if metrics.EnabledExpensive { 231 // If the snap is 'under construction', the first lookup may fail. If that 232 // happens, we don't want to double-count the time elapsed. Thus this 233 // dance with the metering. 234 defer func() { 235 if meter != nil { 236 *meter += time.Since(readStart) 237 } 238 }() 239 } 240 if s.db.snap != nil { 241 if metrics.EnabledExpensive { 242 meter = &s.db.SnapshotStorageReads 243 } 244 // If the object was destructed in *this* block (and potentially resurrected), 245 // the storage has been cleared out, and we should *not* consult the previous 246 // snapshot about any storage values. The only possible alternatives are: 247 // 1) resurrect happened, and new slot values were set -- those should 248 // have been handles via pendingStorage above. 249 // 2) we don't have new values, and can deliver empty response back 250 if _, destructed := s.db.snapDestructs[s.addrHash]; destructed { 251 return common.Hash{} 252 } 253 enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes())) 254 } 255 // If snapshot unavailable or reading from it failed, load from the database 256 if s.db.snap == nil || err != nil { 257 if meter != nil { 258 // If we already spent time checking the snapshot, account for it 259 // and reset the readStart 260 *meter += time.Since(readStart) 261 readStart = time.Now() 262 } 263 if metrics.EnabledExpensive { 264 meter = &s.db.StorageReads 265 } 266 if enc, err = s.getTrie(db).TryGet(key.Bytes()); err != nil { 267 s.setError(err) 268 return common.Hash{} 269 } 270 } 271 var value common.Hash 272 if len(enc) > 0 { 273 _, content, _, err := rlp.Split(enc) 274 if err != nil { 275 s.setError(err) 276 } 277 value.SetBytes(content) 278 } 279 s.originStorage[key] = value 280 return value 281 } 282 283 // SetState updates a value in account storage. 284 func (s *stateObject) SetState(db Database, key, value common.Hash) { 285 // If the fake storage is set, put the temporary state update here. 286 if s.fakeStorage != nil { 287 s.fakeStorage[key] = value 288 return 289 } 290 // If the new value is the same as old, don't set 291 prev := s.GetState(db, key) 292 if prev == value { 293 return 294 } 295 // New value is different, update and journal the change 296 s.db.journal.append(storageChange{ 297 account: &s.address, 298 key: key, 299 prevalue: prev, 300 }) 301 s.setState(key, value) 302 } 303 304 // SetStorage replaces the entire state storage with the given one. 305 // 306 // After this function is called, all original state will be ignored and state 307 // lookup only happens in the fake state storage. 308 // 309 // Note this function should only be used for debugging purpose. 310 func (s *stateObject) SetStorage(storage map[common.Hash]common.Hash) { 311 // Allocate fake storage if it's nil. 312 if s.fakeStorage == nil { 313 s.fakeStorage = make(Storage) 314 } 315 for key, value := range storage { 316 s.fakeStorage[key] = value 317 } 318 // Don't bother journal since this function should only be used for 319 // debugging and the `fake` storage won't be committed to database. 320 } 321 322 func (s *stateObject) setState(key, value common.Hash) { 323 s.dirtyStorage[key] = value 324 } 325 326 // finalise moves all dirty storage slots into the pending area to be hashed or 327 // committed later. It is invoked at the end of every transaction. 328 func (s *stateObject) finalise(prefetch bool) { 329 slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) 330 for key, value := range s.dirtyStorage { 331 s.pendingStorage[key] = value 332 if value != s.originStorage[key] { 333 slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure 334 } 335 } 336 if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot { 337 s.db.prefetcher.prefetch(s.data.Root, slotsToPrefetch) 338 } 339 if len(s.dirtyStorage) > 0 { 340 s.dirtyStorage = make(Storage) 341 } 342 } 343 344 // updateTrie writes cached storage modifications into the object's storage trie. 345 // It will return nil if the trie has not been loaded and no changes have been made 346 func (s *stateObject) updateTrie(db Database) Trie { 347 // Make sure all dirty slots are finalized into the pending storage area 348 s.finalise(false) // Don't prefetch any more, pull directly if need be 349 if len(s.pendingStorage) == 0 { 350 return s.trie 351 } 352 // Track the amount of time wasted on updating the storage trie 353 if metrics.EnabledExpensive { 354 defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) 355 } 356 // The snapshot storage map for the object 357 var storage map[common.Hash][]byte 358 // Insert all the pending updates into the trie 359 tr := s.getTrie(db) 360 hasher := s.db.hasher 361 362 usedStorage := make([][]byte, 0, len(s.pendingStorage)) 363 for key, value := range s.pendingStorage { 364 // Skip noop changes, persist actual changes 365 if value == s.originStorage[key] { 366 continue 367 } 368 s.originStorage[key] = value 369 370 var v []byte 371 if (value == common.Hash{}) { 372 s.setError(tr.TryDelete(key[:])) 373 } else { 374 // Encoding []byte cannot fail, ok to ignore the error. 375 v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) 376 s.setError(tr.TryUpdate(key[:], v)) 377 } 378 // If state snapshotting is active, cache the data til commit 379 if s.db.snap != nil { 380 if storage == nil { 381 // Retrieve the old storage map, if available, create a new one otherwise 382 if storage = s.db.snapStorage[s.addrHash]; storage == nil { 383 storage = make(map[common.Hash][]byte) 384 s.db.snapStorage[s.addrHash] = storage 385 } 386 } 387 storage[crypto.HashData(hasher, key[:])] = v // v will be nil if value is 0x00 388 } 389 usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure 390 } 391 if s.db.prefetcher != nil { 392 s.db.prefetcher.used(s.data.Root, usedStorage) 393 } 394 if len(s.pendingStorage) > 0 { 395 s.pendingStorage = make(Storage) 396 } 397 return tr 398 } 399 400 // UpdateRoot sets the trie root to the current root hash of 401 func (s *stateObject) updateRoot(db Database) { 402 // If nothing changed, don't bother with hashing anything 403 if s.updateTrie(db) == nil { 404 return 405 } 406 // Track the amount of time wasted on hashing the storage trie 407 if metrics.EnabledExpensive { 408 defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) 409 } 410 s.data.Root = s.trie.Hash() 411 } 412 413 // CommitTrie the storage trie of the object to db. 414 // This updates the trie root. 415 func (s *stateObject) CommitTrie(db Database) error { 416 // If nothing changed, don't bother with hashing anything 417 if s.updateTrie(db) == nil { 418 return nil 419 } 420 if s.dbErr != nil { 421 return s.dbErr 422 } 423 // Track the amount of time wasted on committing the storage trie 424 if metrics.EnabledExpensive { 425 defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) 426 } 427 root, err := s.trie.Commit(nil) 428 if err == nil { 429 s.data.Root = root 430 } 431 return err 432 } 433 434 // AddBalance adds amount to s's balance. 435 // It is used to add funds to the destination account of a transfer. 436 func (s *stateObject) AddBalance(amount *big.Int) { 437 // EIP161: We must check emptiness for the objects such that the account 438 // clearing (0,0,0 objects) can take effect. 439 if amount.Sign() == 0 { 440 if s.empty() { 441 s.touch() 442 } 443 return 444 } 445 s.SetBalance(new(big.Int).Add(s.Balance(), amount)) 446 } 447 448 // SubBalance removes amount from s's balance. 449 // It is used to remove funds from the origin account of a transfer. 450 func (s *stateObject) SubBalance(amount *big.Int) { 451 if amount.Sign() == 0 { 452 return 453 } 454 s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) 455 } 456 457 func (s *stateObject) SetBalance(amount *big.Int) { 458 s.db.journal.append(balanceChange{ 459 account: &s.address, 460 prev: new(big.Int).Set(s.data.Balance), 461 }) 462 s.setBalance(amount) 463 } 464 465 // AddBalanceMultiCoin adds amount of coinID to s's balance. 466 // It is used to add multicoin funds to the destination account of a transfer. 467 func (s *stateObject) AddBalanceMultiCoin(coinID common.Hash, amount *big.Int, db Database) { 468 if amount.Sign() == 0 { 469 if s.empty() { 470 s.touch() 471 } 472 473 return 474 } 475 s.SetBalanceMultiCoin(coinID, new(big.Int).Add(s.BalanceMultiCoin(coinID, db), amount), db) 476 } 477 478 // SubBalanceMultiCoin removes amount of coinID from s's balance. 479 // It is used to remove multicoin funds from the origin account of a transfer. 480 func (s *stateObject) SubBalanceMultiCoin(coinID common.Hash, amount *big.Int, db Database) { 481 if amount.Sign() == 0 { 482 return 483 } 484 s.SetBalanceMultiCoin(coinID, new(big.Int).Sub(s.BalanceMultiCoin(coinID, db), amount), db) 485 } 486 487 func (s *stateObject) SetBalanceMultiCoin(coinID common.Hash, amount *big.Int, db Database) { 488 s.EnableMultiCoin() 489 NormalizeCoinID(&coinID) 490 s.SetState(db, coinID, common.BigToHash(amount)) 491 } 492 493 func (s *stateObject) setBalance(amount *big.Int) { 494 s.data.Balance = amount 495 } 496 497 func (s *stateObject) enableMultiCoin() { 498 s.data.IsMultiCoin = true 499 } 500 501 func (s *stateObject) deepCopy(db *StateDB) *stateObject { 502 stateObject := newObject(db, s.address, s.data) 503 if s.trie != nil { 504 stateObject.trie = db.db.CopyTrie(s.trie) 505 } 506 stateObject.code = s.code 507 stateObject.dirtyStorage = s.dirtyStorage.Copy() 508 stateObject.originStorage = s.originStorage.Copy() 509 stateObject.pendingStorage = s.pendingStorage.Copy() 510 stateObject.suicided = s.suicided 511 stateObject.dirtyCode = s.dirtyCode 512 stateObject.deleted = s.deleted 513 return stateObject 514 } 515 516 // 517 // Attribute accessors 518 // 519 520 // Returns the address of the contract/account 521 func (s *stateObject) Address() common.Address { 522 return s.address 523 } 524 525 // Code returns the contract code associated with this object, if any. 526 func (s *stateObject) Code(db Database) []byte { 527 if s.code != nil { 528 return s.code 529 } 530 if bytes.Equal(s.CodeHash(), emptyCodeHash) { 531 return nil 532 } 533 code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) 534 if err != nil { 535 s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) 536 } 537 s.code = code 538 return code 539 } 540 541 // CodeSize returns the size of the contract code associated with this object, 542 // or zero if none. This method is an almost mirror of Code, but uses a cache 543 // inside the database to avoid loading codes seen recently. 544 func (s *stateObject) CodeSize(db Database) int { 545 if s.code != nil { 546 return len(s.code) 547 } 548 if bytes.Equal(s.CodeHash(), emptyCodeHash) { 549 return 0 550 } 551 size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash())) 552 if err != nil { 553 s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) 554 } 555 return size 556 } 557 558 func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { 559 prevcode := s.Code(s.db.db) 560 s.db.journal.append(codeChange{ 561 account: &s.address, 562 prevhash: s.CodeHash(), 563 prevcode: prevcode, 564 }) 565 s.setCode(codeHash, code) 566 } 567 568 func (s *stateObject) setCode(codeHash common.Hash, code []byte) { 569 s.code = code 570 s.data.CodeHash = codeHash[:] 571 s.dirtyCode = true 572 } 573 574 func (s *stateObject) SetNonce(nonce uint64) { 575 s.db.journal.append(nonceChange{ 576 account: &s.address, 577 prev: s.data.Nonce, 578 }) 579 s.setNonce(nonce) 580 } 581 582 func (s *stateObject) setNonce(nonce uint64) { 583 s.dataLock.Lock() 584 defer s.dataLock.Unlock() 585 s.data.Nonce = nonce 586 } 587 588 func (s *stateObject) CodeHash() []byte { 589 return s.data.CodeHash 590 } 591 592 func (s *stateObject) Balance() *big.Int { 593 return s.data.Balance 594 } 595 596 // NormalizeCoinID ORs the 0th bit of the first byte in 597 // [coinID], which ensures this bit will be 1 and all other 598 // bits are left the same. 599 // This partitions multicoin storage from normal state storage. 600 func NormalizeCoinID(coinID *common.Hash) { 601 coinID[0] |= 0x01 602 } 603 604 // NormalizeStateKey ANDs the 0th bit of the first byte in 605 // [key], which ensures this bit will be 0 and all other bits 606 // are left the same. 607 // This partitions normal state storage from multicoin storage. 608 func NormalizeStateKey(key *common.Hash) { 609 key[0] &= 0xfe 610 } 611 612 func (s *stateObject) BalanceMultiCoin(coinID common.Hash, db Database) *big.Int { 613 NormalizeCoinID(&coinID) 614 return s.GetState(db, coinID).Big() 615 } 616 617 func (s *stateObject) EnableMultiCoin() bool { 618 if s.data.IsMultiCoin { 619 return false 620 } 621 s.db.journal.append(multiCoinEnable{ 622 account: &s.address, 623 }) 624 s.enableMultiCoin() 625 return true 626 } 627 628 func (s *stateObject) Nonce() uint64 { 629 s.dataLock.RLock() 630 defer s.dataLock.RUnlock() 631 return s.data.Nonce 632 } 633 634 // Never called, but must be present to allow stateObject to be used 635 // as a vm.Account interface that also satisfies the vm.ContractRef 636 // interface. Interfaces are awesome. 637 func (s *stateObject) Value() *big.Int { 638 panic("Value on stateObject should never be called") 639 }