github.com/MetalBlockchain/subnet-evm@v0.4.9/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/MetalBlockchain/subnet-evm/core/types" 38 "github.com/MetalBlockchain/subnet-evm/metrics" 39 "github.com/MetalBlockchain/subnet-evm/trie" 40 "github.com/ethereum/go-ethereum/common" 41 "github.com/ethereum/go-ethereum/crypto" 42 "github.com/ethereum/go-ethereum/rlp" 43 ) 44 45 var emptyCodeHash = crypto.Keccak256(nil) 46 47 type Code []byte 48 49 func (c Code) String() string { 50 return string(c) //strings.Join(Disassemble(c), " ") 51 } 52 53 type Storage map[common.Hash]common.Hash 54 55 func (s Storage) String() (str string) { 56 for key, value := range s { 57 str += fmt.Sprintf("%X : %X\n", key, value) 58 } 59 60 return 61 } 62 63 func (s Storage) Copy() Storage { 64 cpy := make(Storage, len(s)) 65 for key, value := range s { 66 cpy[key] = value 67 } 68 69 return cpy 70 } 71 72 // stateObject represents an Ethereum account which is being modified. 73 // 74 // The usage pattern is as follows: 75 // First you need to obtain a state object. 76 // Account values can be accessed and modified through the object. 77 // Finally, call CommitTrie to write the modified storage trie into a database. 78 type stateObject struct { 79 address common.Address 80 addrHash common.Hash // hash of ethereum address of the account 81 // dataLock protects the [data] field to prevent a race condition 82 // in the transaction pool tests. TODO remove after re-implementing 83 // tx pool to be synchronous. 84 dataLock sync.RWMutex 85 data types.StateAccount 86 db *StateDB 87 88 // DB error. 89 // State objects are used by the consensus core and VM which are 90 // unable to deal with database-level errors. Any error that occurs 91 // during a database read is memoized here and will eventually be returned 92 // by StateDB.Commit. 93 dbErr error 94 95 // Write caches. 96 trie Trie // storage trie, which becomes non-nil on first access 97 code Code // contract bytecode, which gets set when code is loaded 98 99 originStorage Storage // Storage cache of original entries to dedup rewrites, reset for every transaction 100 pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block 101 dirtyStorage Storage // Storage entries that have been modified in the current transaction execution 102 fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. 103 104 // Cache flags. 105 // When an object is marked suicided it will be delete from the trie 106 // during the "update" phase of the state transition. 107 dirtyCode bool // true if the code was updated 108 suicided bool 109 deleted bool 110 } 111 112 // empty returns whether the account is considered empty. 113 func (s *stateObject) empty() bool { 114 return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) 115 } 116 117 // newObject creates a state object. 118 func newObject(db *StateDB, address common.Address, data types.StateAccount) *stateObject { 119 if data.Balance == nil { 120 data.Balance = new(big.Int) 121 } 122 if data.CodeHash == nil { 123 data.CodeHash = emptyCodeHash 124 } 125 if data.Root == (common.Hash{}) { 126 data.Root = emptyRoot 127 } 128 return &stateObject{ 129 db: db, 130 address: address, 131 addrHash: crypto.Keccak256Hash(address[:]), 132 data: data, 133 originStorage: make(Storage), 134 pendingStorage: make(Storage), 135 dirtyStorage: make(Storage), 136 } 137 } 138 139 // EncodeRLP implements rlp.Encoder. 140 func (s *stateObject) EncodeRLP(w io.Writer) error { 141 return rlp.Encode(w, &s.data) 142 } 143 144 // setError remembers the first non-nil error it is called with. 145 func (s *stateObject) setError(err error) { 146 if s.dbErr == nil { 147 s.dbErr = err 148 } 149 } 150 151 func (s *stateObject) markSuicided() { 152 s.suicided = true 153 } 154 155 func (s *stateObject) touch() { 156 s.db.journal.append(touchChange{ 157 account: &s.address, 158 }) 159 if s.address == ripemd { 160 // Explicitly put it in the dirty-cache, which is otherwise generated from 161 // flattened journals. 162 s.db.journal.dirty(s.address) 163 } 164 } 165 166 func (s *stateObject) getTrie(db Database) Trie { 167 if s.trie == nil { 168 // Try fetching from prefetcher first 169 // We don't prefetch empty tries 170 if s.data.Root != emptyRoot && s.db.prefetcher != nil { 171 // When the miner is creating the pending state, there is no 172 // prefetcher 173 s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root) 174 } 175 if s.trie == nil { 176 var err error 177 s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) 178 if err != nil { 179 s.trie, _ = db.OpenStorageTrie(s.addrHash, common.Hash{}) 180 s.setError(fmt.Errorf("can't create storage trie: %v", err)) 181 } 182 } 183 } 184 return s.trie 185 } 186 187 // GetState retrieves a value from the account storage trie. 188 func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { 189 // If the fake storage is set, only lookup the state here(in the debugging mode) 190 if s.fakeStorage != nil { 191 return s.fakeStorage[key] 192 } 193 // If we have a dirty value for this state entry, return it 194 value, dirty := s.dirtyStorage[key] 195 if dirty { 196 return value 197 } 198 // Otherwise return the entry's original value 199 return s.GetCommittedState(db, key) 200 } 201 202 // GetCommittedState retrieves a value from the committed account storage trie. 203 func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 204 // If the fake storage is set, only lookup the state here(in the debugging mode) 205 if s.fakeStorage != nil { 206 return s.fakeStorage[key] 207 } 208 // If we have a pending write or clean cached, return that 209 if value, pending := s.pendingStorage[key]; pending { 210 return value 211 } 212 if value, cached := s.originStorage[key]; cached { 213 return value 214 } 215 // If no live objects are available, attempt to use snapshots 216 var ( 217 enc []byte 218 err error 219 ) 220 if s.db.snap != nil { 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 := s.db.snapDestructs[s.addrHash]; destructed { 228 return common.Hash{} 229 } 230 start := time.Now() 231 enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes())) 232 if metrics.EnabledExpensive { 233 s.db.SnapshotStorageReads += time.Since(start) 234 } 235 } 236 // If the snapshot is unavailable or reading from it fails, load from the database. 237 if s.db.snap == nil || err != nil { 238 start := time.Now() 239 enc, err = s.getTrie(db).TryGet(key.Bytes()) 240 if metrics.EnabledExpensive { 241 s.db.StorageReads += time.Since(start) 242 } 243 if err != nil { 244 s.setError(err) 245 return common.Hash{} 246 } 247 } 248 var value common.Hash 249 if len(enc) > 0 { 250 _, content, _, err := rlp.Split(enc) 251 if err != nil { 252 s.setError(err) 253 } 254 value.SetBytes(content) 255 } 256 s.originStorage[key] = value 257 return value 258 } 259 260 // SetState updates a value in account storage. 261 func (s *stateObject) SetState(db Database, key, value common.Hash) { 262 // If the fake storage is set, put the temporary state update here. 263 if s.fakeStorage != nil { 264 s.fakeStorage[key] = value 265 return 266 } 267 // If the new value is the same as old, don't set 268 prev := s.GetState(db, key) 269 if prev == value { 270 return 271 } 272 // New value is different, update and journal the change 273 s.db.journal.append(storageChange{ 274 account: &s.address, 275 key: key, 276 prevalue: prev, 277 }) 278 s.setState(key, value) 279 } 280 281 // SetStorage replaces the entire state storage with the given one. 282 // 283 // After this function is called, all original state will be ignored and state 284 // lookup only happens in the fake state storage. 285 // 286 // Note this function should only be used for debugging purpose. 287 func (s *stateObject) SetStorage(storage map[common.Hash]common.Hash) { 288 // Allocate fake storage if it's nil. 289 if s.fakeStorage == nil { 290 s.fakeStorage = make(Storage) 291 } 292 for key, value := range storage { 293 s.fakeStorage[key] = value 294 } 295 // Don't bother journal since this function should only be used for 296 // debugging and the `fake` storage won't be committed to database. 297 } 298 299 func (s *stateObject) setState(key, value common.Hash) { 300 s.dirtyStorage[key] = value 301 } 302 303 // finalise moves all dirty storage slots into the pending area to be hashed or 304 // committed later. It is invoked at the end of every transaction. 305 func (s *stateObject) finalise(prefetch bool) { 306 slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) 307 for key, value := range s.dirtyStorage { 308 s.pendingStorage[key] = value 309 if value != s.originStorage[key] { 310 slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure 311 } 312 } 313 if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot { 314 s.db.prefetcher.prefetch(s.addrHash, s.data.Root, slotsToPrefetch) 315 } 316 if len(s.dirtyStorage) > 0 { 317 s.dirtyStorage = make(Storage) 318 } 319 } 320 321 // updateTrie writes cached storage modifications into the object's storage trie. 322 // It will return nil if the trie has not been loaded and no changes have been made 323 func (s *stateObject) updateTrie(db Database) Trie { 324 // Make sure all dirty slots are finalized into the pending storage area 325 s.finalise(false) // Don't prefetch anymore, pull directly if need be 326 if len(s.pendingStorage) == 0 { 327 return s.trie 328 } 329 // Track the amount of time wasted on updating the storage trie 330 if metrics.EnabledExpensive { 331 defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) 332 } 333 // The snapshot storage map for the object 334 var storage map[common.Hash][]byte 335 // Insert all the pending updates into the trie 336 tr := s.getTrie(db) 337 hasher := s.db.hasher 338 339 usedStorage := make([][]byte, 0, len(s.pendingStorage)) 340 for key, value := range s.pendingStorage { 341 // Skip noop changes, persist actual changes 342 if value == s.originStorage[key] { 343 continue 344 } 345 s.originStorage[key] = value 346 347 var v []byte 348 if (value == common.Hash{}) { 349 s.setError(tr.TryDelete(key[:])) 350 s.db.StorageDeleted += 1 351 } else { 352 // Encoding []byte cannot fail, ok to ignore the error. 353 v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) 354 s.setError(tr.TryUpdate(key[:], v)) 355 s.db.StorageUpdated += 1 356 } 357 // If state snapshotting is active, cache the data til commit 358 if s.db.snap != nil { 359 if storage == nil { 360 // Retrieve the old storage map, if available, create a new one otherwise 361 if storage = s.db.snapStorage[s.addrHash]; storage == nil { 362 storage = make(map[common.Hash][]byte) 363 s.db.snapStorage[s.addrHash] = storage 364 } 365 } 366 storage[crypto.HashData(hasher, key[:])] = v // v will be nil if it's deleted 367 } 368 usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure 369 } 370 if s.db.prefetcher != nil { 371 s.db.prefetcher.used(s.addrHash, s.data.Root, usedStorage) 372 } 373 if len(s.pendingStorage) > 0 { 374 s.pendingStorage = make(Storage) 375 } 376 return tr 377 } 378 379 // UpdateRoot sets the trie root to the current root hash of 380 func (s *stateObject) updateRoot(db Database) { 381 // If nothing changed, don't bother with hashing anything 382 if s.updateTrie(db) == nil { 383 return 384 } 385 // Track the amount of time wasted on hashing the storage trie 386 if metrics.EnabledExpensive { 387 defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) 388 } 389 s.data.Root = s.trie.Hash() 390 } 391 392 // CommitTrie the storage trie of the object to db. 393 // This updates the trie root. 394 func (s *stateObject) CommitTrie(db Database) (*trie.NodeSet, error) { 395 // If nothing changed, don't bother with hashing anything 396 if s.updateTrie(db) == nil { 397 return nil, nil 398 } 399 if s.dbErr != nil { 400 return nil, s.dbErr 401 } 402 // Track the amount of time wasted on committing the storage trie 403 if metrics.EnabledExpensive { 404 defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) 405 } 406 root, nodes, err := s.trie.Commit(false) 407 if err == nil { 408 s.data.Root = root 409 } 410 return nodes, err 411 } 412 413 // AddBalance adds amount to s's balance. 414 // It is used to add funds to the destination account of a transfer. 415 func (s *stateObject) AddBalance(amount *big.Int) { 416 // EIP161: We must check emptiness for the objects such that the account 417 // clearing (0,0,0 objects) can take effect. 418 if amount.Sign() == 0 { 419 if s.empty() { 420 s.touch() 421 } 422 return 423 } 424 s.SetBalance(new(big.Int).Add(s.Balance(), amount)) 425 } 426 427 // SubBalance removes amount from s's balance. 428 // It is used to remove funds from the origin account of a transfer. 429 func (s *stateObject) SubBalance(amount *big.Int) { 430 if amount.Sign() == 0 { 431 return 432 } 433 s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) 434 } 435 436 func (s *stateObject) SetBalance(amount *big.Int) { 437 s.db.journal.append(balanceChange{ 438 account: &s.address, 439 prev: new(big.Int).Set(s.data.Balance), 440 }) 441 s.setBalance(amount) 442 } 443 444 func (s *stateObject) setBalance(amount *big.Int) { 445 s.data.Balance = amount 446 } 447 448 func (s *stateObject) deepCopy(db *StateDB) *stateObject { 449 stateObject := newObject(db, s.address, s.data) 450 if s.trie != nil { 451 stateObject.trie = db.db.CopyTrie(s.trie) 452 } 453 stateObject.code = s.code 454 stateObject.dirtyStorage = s.dirtyStorage.Copy() 455 stateObject.originStorage = s.originStorage.Copy() 456 stateObject.pendingStorage = s.pendingStorage.Copy() 457 stateObject.suicided = s.suicided 458 stateObject.dirtyCode = s.dirtyCode 459 stateObject.deleted = s.deleted 460 return stateObject 461 } 462 463 // 464 // Attribute accessors 465 // 466 467 // Returns the address of the contract/account 468 func (s *stateObject) Address() common.Address { 469 return s.address 470 } 471 472 // Code returns the contract code associated with this object, if any. 473 func (s *stateObject) Code(db Database) []byte { 474 if s.code != nil { 475 return s.code 476 } 477 if bytes.Equal(s.CodeHash(), emptyCodeHash) { 478 return nil 479 } 480 code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) 481 if err != nil { 482 s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) 483 } 484 s.code = code 485 return code 486 } 487 488 // CodeSize returns the size of the contract code associated with this object, 489 // or zero if none. This method is an almost mirror of Code, but uses a cache 490 // inside the database to avoid loading codes seen recently. 491 func (s *stateObject) CodeSize(db Database) int { 492 if s.code != nil { 493 return len(s.code) 494 } 495 if bytes.Equal(s.CodeHash(), emptyCodeHash) { 496 return 0 497 } 498 size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash())) 499 if err != nil { 500 s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) 501 } 502 return size 503 } 504 505 func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { 506 prevcode := s.Code(s.db.db) 507 s.db.journal.append(codeChange{ 508 account: &s.address, 509 prevhash: s.CodeHash(), 510 prevcode: prevcode, 511 }) 512 s.setCode(codeHash, code) 513 } 514 515 func (s *stateObject) setCode(codeHash common.Hash, code []byte) { 516 s.code = code 517 s.data.CodeHash = codeHash[:] 518 s.dirtyCode = true 519 } 520 521 func (s *stateObject) SetNonce(nonce uint64) { 522 s.db.journal.append(nonceChange{ 523 account: &s.address, 524 prev: s.data.Nonce, 525 }) 526 s.setNonce(nonce) 527 } 528 529 func (s *stateObject) setNonce(nonce uint64) { 530 s.dataLock.Lock() 531 defer s.dataLock.Unlock() 532 s.data.Nonce = nonce 533 } 534 535 func (s *stateObject) CodeHash() []byte { 536 return s.data.CodeHash 537 } 538 539 func (s *stateObject) Balance() *big.Int { 540 return s.data.Balance 541 } 542 543 func (s *stateObject) Nonce() uint64 { 544 s.dataLock.RLock() 545 defer s.dataLock.RUnlock() 546 return s.data.Nonce 547 } 548 549 // Never called, but must be present to allow stateObject to be used 550 // as a vm.Account interface that also satisfies the vm.ContractRef 551 // interface. Interfaces are awesome. 552 func (s *stateObject) Value() *big.Int { 553 panic("Value on stateObject should never be called") 554 }