github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/core/state/state_object.go (about)

     1  // Copyright 2014 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"github.com/SmartMeshFoundation/Spectrum/params"
    23  	"github.com/hashicorp/golang-lru"
    24  	"io"
    25  	"math/big"
    26  
    27  	"github.com/SmartMeshFoundation/Spectrum/common"
    28  	"github.com/SmartMeshFoundation/Spectrum/crypto"
    29  	"github.com/SmartMeshFoundation/Spectrum/rlp"
    30  	"github.com/SmartMeshFoundation/Spectrum/trie"
    31  )
    32  
    33  var (
    34  	emptyCodeHash         = crypto.Keccak256(nil)
    35  	contractCodeCacheSize = 5461 // max code size 24k , 128MB / 24k == 5461
    36  	contractCodeCache     *lru.Cache
    37  )
    38  
    39  type Code []byte
    40  
    41  func (self Code) String() string {
    42  	return string(self) //strings.Join(Disassemble(self), " ")
    43  }
    44  
    45  type Storage map[common.Hash]common.Hash
    46  
    47  func (self Storage) String() (str string) {
    48  	for key, value := range self {
    49  		str += fmt.Sprintf("%X : %X\n", key, value)
    50  	}
    51  
    52  	return
    53  }
    54  
    55  func (self Storage) Copy() Storage {
    56  	cpy := make(Storage)
    57  	for key, value := range self {
    58  		cpy[key] = value
    59  	}
    60  
    61  	return cpy
    62  }
    63  
    64  // stateObject represents an Ethereum account which is being modified.
    65  //
    66  // The usage pattern is as follows:
    67  // First you need to obtain a state object.
    68  // Account values can be accessed and modified through the object.
    69  // Finally, call CommitTrie to write the modified storage trie into a database.
    70  type stateObject struct {
    71  	address  common.Address
    72  	addrHash common.Hash // hash of ethereum address of the account
    73  	data     Account
    74  	db       *StateDB
    75  
    76  	// DB error.
    77  	// State objects are used by the consensus core and VM which are
    78  	// unable to deal with database-level errors. Any error that occurs
    79  	// during a database read is memoized here and will eventually be returned
    80  	// by StateDB.Commit.
    81  	dbErr error
    82  
    83  	// Write caches.
    84  	trie Trie // storage trie, which becomes non-nil on first access
    85  	code Code // contract bytecode, which gets set when code is loaded
    86  
    87  	cachedStorage Storage // Storage entry cache to avoid duplicate reads
    88  	dirtyStorage  Storage // Storage entries that need to be flushed to disk
    89  
    90  	// Cache flags.
    91  	// When an object is marked suicided it will be delete from the trie
    92  	// during the "update" phase of the state transition.
    93  	dirtyCode bool // true if the code was updated
    94  	suicided  bool
    95  	touched   bool
    96  	deleted   bool
    97  	onDirty   func(addr common.Address) // Callback method to mark a state object newly dirty
    98  }
    99  
   100  // empty returns whether the account is considered empty.
   101  func (s *stateObject) empty() bool {
   102  	return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
   103  }
   104  
   105  // Account is the Ethereum consensus representation of accounts.
   106  // These objects are stored in the main account trie.
   107  type Account struct {
   108  	Nonce    uint64
   109  	Balance  *big.Int
   110  	Root     common.Hash // merkle root of the storage trie
   111  	CodeHash []byte
   112  }
   113  
   114  // newObject creates a state object.
   115  func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject {
   116  	if contractCodeCache == nil {
   117  		contractCodeCache, _ = lru.New(contractCodeCacheSize)
   118  	}
   119  	if data.Balance == nil {
   120  		data.Balance = new(big.Int)
   121  	}
   122  	if data.CodeHash == nil {
   123  		data.CodeHash = emptyCodeHash
   124  	}
   125  	return &stateObject{
   126  		db:            db,
   127  		address:       address,
   128  		addrHash:      crypto.Keccak256Hash(address[:]),
   129  		data:          data,
   130  		cachedStorage: make(Storage),
   131  		dirtyStorage:  make(Storage),
   132  		onDirty:       onDirty,
   133  	}
   134  }
   135  
   136  // EncodeRLP implements rlp.Encoder.
   137  func (c *stateObject) EncodeRLP(w io.Writer) error {
   138  	return rlp.Encode(w, c.data)
   139  }
   140  
   141  // setError remembers the first non-nil error it is called with.
   142  func (self *stateObject) setError(err error) {
   143  	if self.dbErr == nil {
   144  		self.dbErr = err
   145  	}
   146  }
   147  
   148  func (self *stateObject) markSuicided() {
   149  	self.suicided = true
   150  	if self.onDirty != nil {
   151  		self.onDirty(self.Address())
   152  		self.onDirty = nil
   153  	}
   154  }
   155  
   156  func (c *stateObject) touch() {
   157  	c.db.journal = append(c.db.journal, touchChange{
   158  		account: &c.address,
   159  	})
   160  	if c.onDirty != nil {
   161  		c.onDirty(c.Address())
   162  		c.onDirty = nil
   163  	}
   164  	c.touched = true
   165  }
   166  
   167  func (c *stateObject) getTrie(db Database) Trie {
   168  	if c.trie == nil {
   169  		var err error
   170  		c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root)
   171  		if err != nil {
   172  			c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{})
   173  			c.setError(fmt.Errorf("can't create storage trie: %v", err))
   174  		}
   175  	}
   176  	return c.trie
   177  }
   178  
   179  // GetState returns a value in account storage.
   180  func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
   181  	value, exists := self.cachedStorage[key]
   182  	if exists {
   183  		return value
   184  	}
   185  	// Load from DB in case it is missing.
   186  	enc, err := self.getTrie(db).TryGet(key[:])
   187  	if err != nil {
   188  		self.setError(err)
   189  		return common.Hash{}
   190  	}
   191  	if len(enc) > 0 {
   192  		_, content, _, err := rlp.Split(enc)
   193  		if err != nil {
   194  			self.setError(err)
   195  		}
   196  		value.SetBytes(content)
   197  	}
   198  	if (value != common.Hash{}) {
   199  		self.cachedStorage[key] = value
   200  	}
   201  	return value
   202  }
   203  
   204  // SetState updates a value in account storage.
   205  func (self *stateObject) SetState(db Database, key, value common.Hash) {
   206  	self.db.journal = append(self.db.journal, storageChange{
   207  		account:  &self.address,
   208  		key:      key,
   209  		prevalue: self.GetState(db, key),
   210  	})
   211  	self.setState(key, value)
   212  }
   213  
   214  func (self *stateObject) setState(key, value common.Hash) {
   215  	self.cachedStorage[key] = value
   216  	self.dirtyStorage[key] = value
   217  
   218  	if self.onDirty != nil {
   219  		self.onDirty(self.Address())
   220  		self.onDirty = nil
   221  	}
   222  }
   223  
   224  // updateTrie writes cached storage modifications into the object's storage trie.
   225  func (self *stateObject) updateTrie(db Database) Trie {
   226  	tr := self.getTrie(db)
   227  	for key, value := range self.dirtyStorage {
   228  		delete(self.dirtyStorage, key)
   229  		if (value == common.Hash{}) {
   230  			self.setError(tr.TryDelete(key[:]))
   231  			continue
   232  		}
   233  		// Encoding []byte cannot fail, ok to ignore the error.
   234  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
   235  		self.setError(tr.TryUpdate(key[:], v))
   236  	}
   237  	return tr
   238  }
   239  
   240  // UpdateRoot sets the trie root to the current root hash of
   241  func (self *stateObject) updateRoot(db Database) {
   242  	self.updateTrie(db)
   243  	self.data.Root = self.trie.Hash()
   244  }
   245  
   246  // CommitTrie the storage trie of the object to dwb.
   247  // This updates the trie root.
   248  func (self *stateObject) CommitTrie(db Database, dbw trie.DatabaseWriter) error {
   249  	self.updateTrie(db)
   250  	if self.dbErr != nil {
   251  		return self.dbErr
   252  	}
   253  	root, err := self.trie.CommitTo(dbw)
   254  	if err == nil {
   255  		self.data.Root = root
   256  	}
   257  	return err
   258  }
   259  
   260  // AddBalance removes amount from c's balance.
   261  // It is used to add funds to the destination account of a transfer.
   262  func (c *stateObject) AddBalance(amount *big.Int) {
   263  	// EIP158: We must check emptiness for the objects such that the account
   264  	// clearing (0,0,0 objects) can take effect.
   265  	if amount.Sign() == 0 {
   266  		if c.empty() {
   267  			c.touch()
   268  		}
   269  
   270  		return
   271  	}
   272  	c.SetBalance(new(big.Int).Add(c.Balance(), amount))
   273  }
   274  
   275  // SubBalance removes amount from c's balance.
   276  // It is used to remove funds from the origin account of a transfer.
   277  func (c *stateObject) SubBalance(amount *big.Int) {
   278  	if amount.Sign() == 0 {
   279  		return
   280  	}
   281  	c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
   282  }
   283  
   284  func (self *stateObject) SetBalance(amount *big.Int) {
   285  	self.db.journal = append(self.db.journal, balanceChange{
   286  		account: &self.address,
   287  		prev:    new(big.Int).Set(self.data.Balance),
   288  	})
   289  	self.setBalance(amount)
   290  }
   291  
   292  func (self *stateObject) setBalance(amount *big.Int) {
   293  	self.data.Balance = amount
   294  	if self.onDirty != nil {
   295  		self.onDirty(self.Address())
   296  		self.onDirty = nil
   297  	}
   298  }
   299  
   300  // Return the gas back to the origin. Used by the Virtual machine or Closures
   301  func (c *stateObject) ReturnGas(gas *big.Int) {}
   302  
   303  func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject {
   304  	stateObject := newObject(db, self.address, self.data, onDirty)
   305  	if self.trie != nil {
   306  		stateObject.trie = db.db.CopyTrie(self.trie)
   307  	}
   308  	stateObject.code = self.code
   309  	stateObject.dirtyStorage = self.dirtyStorage.Copy()
   310  	stateObject.cachedStorage = self.dirtyStorage.Copy()
   311  	stateObject.suicided = self.suicided
   312  	stateObject.dirtyCode = self.dirtyCode
   313  	stateObject.deleted = self.deleted
   314  	return stateObject
   315  }
   316  
   317  //
   318  // Attribute accessors
   319  //
   320  
   321  // Returns the address of the contract/account
   322  func (c *stateObject) Address() common.Address {
   323  	return c.address
   324  }
   325  
   326  func (self *stateObject) getCode(db Database) ([]byte, error) {
   327  	var (
   328  		code []byte
   329  		err  error
   330  	)
   331  	if contractCodeCache == nil {
   332  		code, err = db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   333  		return code, err
   334  	}
   335  	val, ok := contractCodeCache.Get(self.Address())
   336  	if ok {
   337  		return val.([]byte), nil
   338  	}
   339  	code, err = db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   340  	if err != nil {
   341  		return nil, err
   342  	}
   343  	contractCodeCache.Add(self.Address(), code)
   344  	return code, err
   345  }
   346  
   347  // Code returns the contract code associated with this object, if any.
   348  func (self *stateObject) Code(db Database) []byte {
   349  	var (
   350  		code []byte
   351  		err  error
   352  	)
   353  	if self.code != nil {
   354  		return self.code
   355  	}
   356  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   357  		return nil
   358  	}
   359  	// add by liangc : cache chief contract code
   360  	if params.IsChiefAddress(self.Address()) {
   361  		code, err = params.GetChiefContractCode(self.Address())
   362  		if err != nil {
   363  			code, err = db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   364  			if err == nil {
   365  				params.SetChiefContractCode(self.Address(), code)
   366  			}
   367  		}
   368  	} else {
   369  		// TODO LRU cache
   370  		//code, err = db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   371  		code, err = self.getCode(db)
   372  	}
   373  
   374  	if err != nil {
   375  		self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
   376  	}
   377  	self.code = code
   378  	return code
   379  }
   380  
   381  func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
   382  	prevcode := self.Code(self.db.db)
   383  	self.db.journal = append(self.db.journal, codeChange{
   384  		account:  &self.address,
   385  		prevhash: self.CodeHash(),
   386  		prevcode: prevcode,
   387  	})
   388  	self.setCode(codeHash, code)
   389  }
   390  
   391  func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
   392  	self.code = code
   393  	self.data.CodeHash = codeHash[:]
   394  	self.dirtyCode = true
   395  	if self.onDirty != nil {
   396  		self.onDirty(self.Address())
   397  		self.onDirty = nil
   398  	}
   399  }
   400  
   401  func (self *stateObject) SetNonce(nonce uint64) {
   402  	self.db.journal = append(self.db.journal, nonceChange{
   403  		account: &self.address,
   404  		prev:    self.data.Nonce,
   405  	})
   406  	self.setNonce(nonce)
   407  }
   408  
   409  func (self *stateObject) setNonce(nonce uint64) {
   410  	self.data.Nonce = nonce
   411  	if self.onDirty != nil {
   412  		self.onDirty(self.Address())
   413  		self.onDirty = nil
   414  	}
   415  }
   416  
   417  func (self *stateObject) CodeHash() []byte {
   418  	return self.data.CodeHash
   419  }
   420  
   421  func (self *stateObject) Balance() *big.Int {
   422  	return self.data.Balance
   423  }
   424  
   425  func (self *stateObject) Nonce() uint64 {
   426  	return self.data.Nonce
   427  }
   428  
   429  // Never called, but must be present to allow stateObject to be used
   430  // as a vm.Account interface that also satisfies the vm.ContractRef
   431  // interface. Interfaces are awesome.
   432  func (self *stateObject) Value() *big.Int {
   433  	panic("Value on stateObject should never be called")
   434  }