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