github.com/klaytn/klaytn@v1.10.2/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 (self Code) String() string {
    47  	return string(self) // strings.Join(Disassemble(self), " ")
    48  }
    49  
    50  type Storage map[common.Hash]common.Hash
    51  
    52  func (self Storage) String() (str string) {
    53  	for key, value := range self {
    54  		str += fmt.Sprintf("%X : %X\n", key, value)
    55  	}
    56  
    57  	return
    58  }
    59  
    60  func (self Storage) Copy() Storage {
    61  	cpy := make(Storage)
    62  	for key, value := range self {
    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 suicided 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  	suicided  bool
   101  	deleted   bool
   102  
   103  	encoded atomic.Value // RLP-encoded data
   104  }
   105  
   106  type encodedData struct {
   107  	err         error  // RLP-encoding error from stateObjectEncoder
   108  	data        []byte // RLP-encoded stateObject
   109  	trieHashKey []byte // hash of key used to update trie
   110  	trieHexKey  []byte // hex string of tireHashKey
   111  }
   112  
   113  // empty returns whether the account is considered empty.
   114  func (s *stateObject) empty() bool {
   115  	return s.account.Empty()
   116  }
   117  
   118  // newObject creates a state object.
   119  func newObject(db *StateDB, address common.Address, data account.Account) *stateObject {
   120  	return &stateObject{
   121  		db:            db,
   122  		address:       address,
   123  		addrHash:      crypto.Keccak256Hash(address[:]),
   124  		account:       data,
   125  		originStorage: make(Storage),
   126  		dirtyStorage:  make(Storage),
   127  	}
   128  }
   129  
   130  // EncodeRLP implements rlp.Encoder.
   131  func (c *stateObject) EncodeRLP(w io.Writer) error {
   132  	serializer := account.NewAccountSerializerWithAccount(c.account)
   133  	return rlp.Encode(w, serializer)
   134  }
   135  
   136  // setError remembers the first non-nil error it is called with.
   137  func (self *stateObject) setError(err error) {
   138  	if self.dbErr == nil {
   139  		self.dbErr = err
   140  	}
   141  }
   142  
   143  func (self *stateObject) markSuicided() {
   144  	self.suicided = true
   145  }
   146  
   147  func (c *stateObject) touch() {
   148  	c.db.journal.append(touchChange{
   149  		account: &c.address,
   150  	})
   151  	if c.address == ripemd {
   152  		// Explicitly put it in the dirty-cache, which is otherwise generated from
   153  		// flattened journals.
   154  		c.db.journal.dirty(c.address)
   155  	}
   156  }
   157  
   158  func (c *stateObject) openStorageTrie(hash common.Hash, db Database) (Trie, error) {
   159  	if c.db.prefetching {
   160  		return db.OpenStorageTrieForPrefetching(hash)
   161  	}
   162  	return db.OpenStorageTrie(hash)
   163  }
   164  
   165  func (c *stateObject) getStorageTrie(db Database) Trie {
   166  	if c.storageTrie == nil {
   167  		if acc := account.GetProgramAccount(c.account); acc != nil {
   168  			var err error
   169  			c.storageTrie, err = c.openStorageTrie(acc.GetStorageRoot(), db)
   170  			if err != nil {
   171  				c.storageTrie, _ = c.openStorageTrie(common.Hash{}, db)
   172  				c.setError(fmt.Errorf("can't create storage trie: %v", err))
   173  			}
   174  		} else {
   175  			// not a contract account, just returns the empty trie.
   176  			c.storageTrie, _ = c.openStorageTrie(common.Hash{}, db)
   177  		}
   178  	}
   179  	return c.storageTrie
   180  }
   181  
   182  // GetState retrieves a value from the account storage trie.
   183  func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
   184  	// If we have a dirty value for this state entry, return it
   185  	value, dirty := self.dirtyStorage[key]
   186  	if dirty {
   187  		return value
   188  	}
   189  	// Otherwise return the entry's original value
   190  	return self.GetCommittedState(db, key)
   191  }
   192  
   193  // GetCommittedState retrieves a value from the committed account storage trie.
   194  func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash {
   195  	// If we have the original value cached, return that
   196  	value, cached := self.originStorage[key]
   197  	if cached {
   198  		return value
   199  	}
   200  	// Track the amount of time wasted on reading the storage trie
   201  	var (
   202  		enc   []byte
   203  		err   error
   204  		meter *time.Duration
   205  	)
   206  	readStart := time.Now()
   207  	if EnabledExpensive {
   208  		// If the snap is 'under construction', the first lookup may fail. If that
   209  		// happens, we don't want to double-count the time elapsed. Thus this
   210  		// dance with the metering.
   211  		defer func(start time.Time) {
   212  			if meter != nil {
   213  				*meter += time.Since(readStart)
   214  			}
   215  		}(time.Now())
   216  	}
   217  	if self.db.snap != nil {
   218  		if EnabledExpensive {
   219  			meter = &self.db.SnapshotStorageReads
   220  		}
   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 := self.db.snapDestructs[self.addrHash]; destructed {
   228  			return common.Hash{}
   229  		}
   230  		enc, err = self.db.snap.Storage(self.addrHash, crypto.Keccak256Hash(key.Bytes()))
   231  	}
   232  	// If the snapshot is unavailable or reading from it fails, load from the database.
   233  	if self.db.snap == nil || err != nil {
   234  		if EnabledExpensive {
   235  			if meter != nil {
   236  				// If we already spent time checking the snapshot, account for it
   237  				// and reset the readStart
   238  				*meter += time.Since(readStart)
   239  				readStart = time.Now()
   240  			}
   241  			meter = &self.db.StorageReads
   242  		}
   243  		// Load from DB in case it is missing.
   244  		if enc, err = self.getStorageTrie(db).TryGet(key[:]); err != nil {
   245  			self.setError(err)
   246  			return common.Hash{}
   247  		}
   248  	}
   249  	if len(enc) > 0 {
   250  		_, content, _, err := rlp.Split(enc)
   251  		if err != nil {
   252  			self.setError(err)
   253  		}
   254  		value.SetBytes(content)
   255  	}
   256  	self.originStorage[key] = value
   257  	return value
   258  }
   259  
   260  // SetState updates a value in account trie.
   261  func (self *stateObject) SetState(db Database, key, value common.Hash) {
   262  	// If the new value is the same as old, don't set
   263  	prev := self.GetState(db, key)
   264  	if prev == value {
   265  		return
   266  	}
   267  	// New value is different, update and journal the change
   268  	self.db.journal.append(storageChange{
   269  		account:  &self.address,
   270  		key:      key,
   271  		prevalue: prev,
   272  	})
   273  	self.setState(key, value)
   274  }
   275  
   276  // SetStorage replaces the entire state storage with the given one.
   277  //
   278  // After this function is called, all original state will be ignored and state
   279  // lookup only happens in the fake state storage.
   280  //
   281  // Note this function should only be used for debugging purpose.
   282  func (self *stateObject) SetStorage(storage map[common.Hash]common.Hash) {
   283  	// Allocate fake storage if it's nil.
   284  	if self.fakeStorage == nil {
   285  		self.fakeStorage = make(Storage)
   286  	}
   287  	for key, value := range storage {
   288  		self.fakeStorage[key] = value
   289  	}
   290  	// Don't bother journal since this function should only be used for
   291  	// debugging and the `fake` storage won't be committed to database.
   292  }
   293  
   294  // IsContractAccount returns true is the account has a non-empty codeHash.
   295  func (self *stateObject) IsContractAccount() bool {
   296  	acc := account.GetProgramAccount(self.account)
   297  	if acc != nil && !bytes.Equal(acc.GetCodeHash(), emptyCodeHash) {
   298  		return true
   299  	}
   300  	return false
   301  }
   302  
   303  // IsContractAvailable returns true if the account has a smart contract code hash and didn't self-destruct
   304  func (self *stateObject) IsContractAvailable() bool {
   305  	acc := account.GetProgramAccount(self.account)
   306  	if acc != nil && !bytes.Equal(acc.GetCodeHash(), emptyCodeHash) && self.suicided == false {
   307  		return true
   308  	}
   309  	return false
   310  }
   311  
   312  // IsProgramAccount returns true if the account implements ProgramAccount.
   313  func (self *stateObject) IsProgramAccount() bool {
   314  	return account.GetProgramAccount(self.account) != nil
   315  }
   316  
   317  func (self *stateObject) GetKey() accountkey.AccountKey {
   318  	if ak := account.GetAccountWithKey(self.account); ak != nil {
   319  		return ak.GetKey()
   320  	}
   321  	return accountkey.NewAccountKeyLegacy()
   322  }
   323  
   324  func (self *stateObject) setState(key, value common.Hash) {
   325  	self.dirtyStorage[key] = value
   326  }
   327  
   328  func (self *stateObject) UpdateKey(newKey accountkey.AccountKey, currentBlockNumber uint64) error {
   329  	return self.account.UpdateKey(newKey, currentBlockNumber)
   330  }
   331  
   332  // updateStorageTrie writes cached storage modifications into the object's storage trie.
   333  func (self *stateObject) updateStorageTrie(db Database) Trie {
   334  	// Track the amount of time wasted on updating the storage trie
   335  	if EnabledExpensive {
   336  		defer func(start time.Time) { self.db.StorageUpdates += time.Since(start) }(time.Now())
   337  	}
   338  	// The snapshot storage map for the object
   339  	var storage map[common.Hash][]byte
   340  	// Insert all the pending updates into the trie
   341  	tr := self.getStorageTrie(db)
   342  	for key, value := range self.dirtyStorage {
   343  		delete(self.dirtyStorage, key)
   344  
   345  		// Skip noop changes, persist actual changes
   346  		if value == self.originStorage[key] {
   347  			continue
   348  		}
   349  		self.originStorage[key] = value
   350  
   351  		var v []byte
   352  		if (value == common.Hash{}) {
   353  			self.setError(tr.TryDelete(key[:]))
   354  		} else {
   355  			// Encoding []byte cannot fail, ok to ignore the error.
   356  			v, _ = rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
   357  			self.setError(tr.TryUpdate(key[:], v))
   358  		}
   359  		// If state snapshotting is active, cache the data til commit
   360  		if self.db.snap != nil {
   361  			if storage == nil {
   362  				// Retrieve the old storage map, if available, create a new one otherwise
   363  				if storage = self.db.snapStorage[self.addrHash]; storage == nil {
   364  					storage = make(map[common.Hash][]byte)
   365  					self.db.snapStorage[self.addrHash] = storage
   366  				}
   367  			}
   368  			storage[crypto.Keccak256Hash(key[:])] = v // v will be nil if it's deleted
   369  		}
   370  	}
   371  	return tr
   372  }
   373  
   374  // updateStorageRoot sets the storage trie root to the newly updated one.
   375  func (self *stateObject) updateStorageRoot(db Database) {
   376  	if acc := account.GetProgramAccount(self.account); acc != nil {
   377  		// Track the amount of time wasted on hashing the storage trie
   378  		if EnabledExpensive {
   379  			defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now())
   380  		}
   381  		acc.SetStorageRoot(self.storageTrie.Hash())
   382  	}
   383  }
   384  
   385  // setStorageRoot calls SetStorageRoot if updateStorageRoot flag is given true.
   386  // Otherwise, it just marks the object and update their root hash later.
   387  func (self *stateObject) setStorageRoot(updateStorageRoot bool, objectsToUpdate map[common.Address]struct{}) {
   388  	if acc := account.GetProgramAccount(self.account); acc != nil {
   389  		if updateStorageRoot {
   390  			// Track the amount of time wasted on hashing the storage trie
   391  			if EnabledExpensive {
   392  				defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now())
   393  			}
   394  			acc.SetStorageRoot(self.storageTrie.Hash())
   395  			return
   396  		}
   397  		// If updateStorageRoot == false, it just marks the object and updates its storage root later.
   398  		objectsToUpdate[self.Address()] = struct{}{}
   399  	}
   400  }
   401  
   402  // CommitStorageTrie writes the storage trie of the object to db.
   403  // This updates the storage trie root.
   404  func (self *stateObject) CommitStorageTrie(db Database) error {
   405  	self.updateStorageTrie(db)
   406  	if self.dbErr != nil {
   407  		return self.dbErr
   408  	}
   409  	// Track the amount of time wasted on committing the storage trie
   410  	if EnabledExpensive {
   411  		defer func(start time.Time) { self.db.StorageCommits += time.Since(start) }(time.Now())
   412  	}
   413  	if acc := account.GetProgramAccount(self.account); acc != nil {
   414  		root, err := self.storageTrie.Commit(nil)
   415  		if err != nil {
   416  			return err
   417  		}
   418  		acc.SetStorageRoot(root)
   419  	}
   420  	return nil
   421  }
   422  
   423  // AddBalance removes amount from c's balance.
   424  // It is used to add funds to the destination account of a transfer.
   425  func (c *stateObject) AddBalance(amount *big.Int) {
   426  	// EIP158: We must check emptiness for the objects such that the account
   427  	// clearing (0,0,0 objects) can take effect.
   428  	if amount.Sign() == 0 {
   429  		if c.empty() {
   430  			c.touch()
   431  		}
   432  
   433  		return
   434  	}
   435  	c.SetBalance(new(big.Int).Add(c.Balance(), amount))
   436  }
   437  
   438  // SubBalance removes amount from c's balance.
   439  // It is used to remove funds from the origin account of a transfer.
   440  func (c *stateObject) SubBalance(amount *big.Int) {
   441  	if amount.Sign() == 0 {
   442  		return
   443  	}
   444  	c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
   445  }
   446  
   447  func (self *stateObject) SetBalance(amount *big.Int) {
   448  	self.db.journal.append(balanceChange{
   449  		account: &self.address,
   450  		prev:    new(big.Int).Set(self.account.GetBalance()),
   451  	})
   452  	self.setBalance(amount)
   453  }
   454  
   455  func (self *stateObject) setBalance(amount *big.Int) {
   456  	self.account.SetBalance(amount)
   457  }
   458  
   459  // Return the gas back to the origin. Used by the Virtual machine or Closures
   460  func (c *stateObject) ReturnGas(gas *big.Int) {}
   461  
   462  func (self *stateObject) deepCopy(db *StateDB) *stateObject {
   463  	stateObject := newObject(db, self.address, self.account.DeepCopy())
   464  	if self.storageTrie != nil {
   465  		stateObject.storageTrie = db.db.CopyTrie(self.storageTrie)
   466  	}
   467  	stateObject.code = self.code
   468  	stateObject.dirtyStorage = self.dirtyStorage.Copy()
   469  	stateObject.originStorage = self.originStorage.Copy()
   470  	stateObject.suicided = self.suicided
   471  	stateObject.dirtyCode = self.dirtyCode
   472  	stateObject.deleted = self.deleted
   473  	return stateObject
   474  }
   475  
   476  //
   477  // Attribute accessors
   478  //
   479  
   480  // Returns the address of the contract/account
   481  func (c *stateObject) Address() common.Address {
   482  	return c.address
   483  }
   484  
   485  // Code returns the contract code associated with this object, if any.
   486  func (self *stateObject) Code(db Database) []byte {
   487  	if self.code != nil {
   488  		return self.code
   489  	}
   490  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   491  		return nil
   492  	}
   493  	code, err := db.ContractCode(common.BytesToHash(self.CodeHash()))
   494  	if err != nil {
   495  		self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
   496  	}
   497  	self.code = code
   498  	return code
   499  }
   500  
   501  // CodeSize returns the size of the contract code associated with this object,
   502  // or zero if none. This method is an almost mirror of Code, but uses a cache
   503  // inside the database to avoid loading codes seen recently.
   504  func (self *stateObject) CodeSize(db Database) int {
   505  	if self.code != nil {
   506  		return len(self.code)
   507  	}
   508  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   509  		return 0
   510  	}
   511  	size, err := db.ContractCodeSize(common.BytesToHash(self.CodeHash()))
   512  	if err != nil {
   513  		self.setError(fmt.Errorf("can't load code size %x: %v", self.CodeHash(), err))
   514  	}
   515  	return size
   516  }
   517  
   518  func (self *stateObject) SetCode(codeHash common.Hash, code []byte) error {
   519  	prevcode := self.Code(self.db.db)
   520  	self.db.journal.append(codeChange{
   521  		account:  &self.address,
   522  		prevhash: self.CodeHash(),
   523  		prevcode: prevcode,
   524  	})
   525  	return self.setCode(codeHash, code)
   526  }
   527  
   528  func (self *stateObject) setCode(codeHash common.Hash, code []byte) error {
   529  	acc := account.GetProgramAccount(self.account)
   530  	if acc == nil {
   531  		logger.Error("setCode() should be called only to a ProgramAccount!", "account address", self.address)
   532  		return kerrors.ErrNotProgramAccount
   533  	}
   534  	self.code = code
   535  	acc.SetCodeHash(codeHash[:])
   536  	self.dirtyCode = true
   537  	return nil
   538  }
   539  
   540  // IncNonce increases the nonce of the account by one with making a journal of the previous nonce.
   541  func (self *stateObject) IncNonce() {
   542  	nonce := self.account.GetNonce()
   543  	self.db.journal.append(nonceChange{
   544  		account: &self.address,
   545  		prev:    nonce,
   546  	})
   547  	self.setNonce(nonce + 1)
   548  }
   549  
   550  func (self *stateObject) SetNonce(nonce uint64) {
   551  	self.db.journal.append(nonceChange{
   552  		account: &self.address,
   553  		prev:    self.account.GetNonce(),
   554  	})
   555  	self.setNonce(nonce)
   556  }
   557  
   558  func (self *stateObject) setNonce(nonce uint64) {
   559  	self.account.SetNonce(nonce)
   560  }
   561  
   562  func (self *stateObject) CodeHash() []byte {
   563  	if acc := account.GetProgramAccount(self.account); acc != nil {
   564  		return acc.GetCodeHash()
   565  	}
   566  	return emptyCodeHash
   567  }
   568  
   569  func (self *stateObject) Balance() *big.Int {
   570  	return self.account.GetBalance()
   571  }
   572  
   573  //func (self *stateObject) HumanReadable() bool {
   574  //	return self.account.GetHumanReadable()
   575  //}
   576  
   577  func (self *stateObject) Nonce() uint64 {
   578  	return self.account.GetNonce()
   579  }
   580  
   581  // Never called, but must be present to allow stateObject to be used
   582  // as a vm.Account interface that also satisfies the vm.ContractRef
   583  // interface. Interfaces are awesome.
   584  func (self *stateObject) Value() *big.Int {
   585  	panic("Value on stateObject should never be called")
   586  }