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  }