github.com/klaytn/klaytn@v1.12.1/blockchain/state/state_object.go (about)

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