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