github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/core/state/state_object.go (about)

     1  package state
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"math/big"
     8  
     9  	"github.com/neatlab/neatio/utilities/common"
    10  	"github.com/neatlab/neatio/utilities/crypto"
    11  	"github.com/neatlab/neatio/utilities/rlp"
    12  )
    13  
    14  var emptyCodeHash = crypto.Keccak256(nil)
    15  
    16  type Code []byte
    17  
    18  func (self Code) String() string {
    19  	return string(self)
    20  }
    21  
    22  type Storage map[common.Hash]common.Hash
    23  
    24  func (self Storage) String() (str string) {
    25  	for key, value := range self {
    26  		str += fmt.Sprintf("%X : %X\n", key, value)
    27  	}
    28  
    29  	return
    30  }
    31  
    32  func (self Storage) Copy() Storage {
    33  	cpy := make(Storage)
    34  	for key, value := range self {
    35  		cpy[key] = value
    36  	}
    37  
    38  	return cpy
    39  }
    40  
    41  type stateObject struct {
    42  	address  common.Address
    43  	addrHash common.Hash
    44  	data     Account
    45  	db       *StateDB
    46  
    47  	dbErr error
    48  
    49  	trie Trie
    50  	code Code
    51  
    52  	originStorage Storage
    53  	dirtyStorage  Storage
    54  
    55  	tx1Trie Trie
    56  	tx3Trie Trie
    57  
    58  	dirtyTX1 map[common.Hash]struct{}
    59  	dirtyTX3 map[common.Hash]struct{}
    60  
    61  	proxiedTrie   Trie
    62  	originProxied Proxied
    63  	dirtyProxied  Proxied
    64  
    65  	rewardTrie   Trie
    66  	originReward Reward
    67  	dirtyReward  Reward
    68  
    69  	dirtyCode bool
    70  	suicided  bool
    71  	touched   bool
    72  	deleted   bool
    73  	onDirty   func(addr common.Address)
    74  }
    75  
    76  func (s *stateObject) empty() bool {
    77  	return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) && s.data.DepositBalance.Sign() == 0 && len(s.data.SideChainDepositBalance) == 0 && s.data.ChainBalance.Sign() == 0 && s.data.DelegateBalance.Sign() == 0 && s.data.ProxiedBalance.Sign() == 0 && s.data.DepositProxiedBalance.Sign() == 0 && s.data.PendingRefundBalance.Sign() == 0
    78  }
    79  
    80  type Account struct {
    81  	Nonce                   uint64
    82  	Balance                 *big.Int
    83  	DepositBalance          *big.Int
    84  	SideChainDepositBalance []*sideChainDepositBalance
    85  	ChainBalance            *big.Int
    86  	Root                    common.Hash
    87  	TX1Root                 common.Hash
    88  	TX3Root                 common.Hash
    89  	CodeHash                []byte
    90  
    91  	DelegateBalance       *big.Int
    92  	ProxiedBalance        *big.Int
    93  	DepositProxiedBalance *big.Int
    94  	PendingRefundBalance  *big.Int
    95  	ProxiedRoot           common.Hash
    96  
    97  	Candidate  bool
    98  	Commission uint8
    99  
   100  	Pubkey   string
   101  	FAddress common.Address
   102  
   103  	RewardBalance *big.Int
   104  
   105  	RewardRoot common.Hash
   106  }
   107  
   108  func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject {
   109  	if data.Balance == nil {
   110  		data.Balance = new(big.Int)
   111  	}
   112  	if data.DepositBalance == nil {
   113  		data.DepositBalance = new(big.Int)
   114  	}
   115  	if data.ChainBalance == nil {
   116  		data.ChainBalance = new(big.Int)
   117  	}
   118  
   119  	if data.DelegateBalance == nil {
   120  		data.DelegateBalance = new(big.Int)
   121  	}
   122  	if data.ProxiedBalance == nil {
   123  		data.ProxiedBalance = new(big.Int)
   124  	}
   125  	if data.DepositProxiedBalance == nil {
   126  		data.DepositProxiedBalance = new(big.Int)
   127  	}
   128  	if data.PendingRefundBalance == nil {
   129  		data.PendingRefundBalance = new(big.Int)
   130  	}
   131  
   132  	if data.RewardBalance == nil {
   133  		data.RewardBalance = new(big.Int)
   134  	}
   135  
   136  	if data.CodeHash == nil {
   137  		data.CodeHash = emptyCodeHash
   138  	}
   139  	return &stateObject{
   140  		db:            db,
   141  		address:       address,
   142  		addrHash:      crypto.Keccak256Hash(address[:]),
   143  		data:          data,
   144  		originStorage: make(Storage),
   145  		dirtyStorage:  make(Storage),
   146  		dirtyTX1:      make(map[common.Hash]struct{}),
   147  		dirtyTX3:      make(map[common.Hash]struct{}),
   148  		originProxied: make(Proxied),
   149  		dirtyProxied:  make(Proxied),
   150  		originReward:  make(Reward),
   151  		dirtyReward:   make(Reward),
   152  		onDirty:       onDirty,
   153  	}
   154  }
   155  
   156  func (c *stateObject) EncodeRLP(w io.Writer) error {
   157  	return rlp.Encode(w, c.data)
   158  }
   159  
   160  func (self *stateObject) setError(err error) {
   161  	if self.dbErr == nil {
   162  		self.dbErr = err
   163  	}
   164  }
   165  
   166  func (self *stateObject) markSuicided() {
   167  	self.suicided = true
   168  	if self.onDirty != nil {
   169  		self.onDirty(self.Address())
   170  		self.onDirty = nil
   171  	}
   172  }
   173  
   174  func (c *stateObject) touch() {
   175  	c.db.journal = append(c.db.journal, touchChange{
   176  		account:   &c.address,
   177  		prev:      c.touched,
   178  		prevDirty: c.onDirty == nil,
   179  	})
   180  	if c.onDirty != nil {
   181  		c.onDirty(c.Address())
   182  		c.onDirty = nil
   183  	}
   184  	c.touched = true
   185  }
   186  
   187  func (c *stateObject) getTX1Trie(db Database) Trie {
   188  	if c.tx1Trie == nil {
   189  		var err error
   190  		c.tx1Trie, err = db.OpenTX1Trie(c.addrHash, c.data.TX1Root)
   191  		if err != nil {
   192  			c.tx1Trie, _ = db.OpenTX1Trie(c.addrHash, common.Hash{})
   193  			c.setError(fmt.Errorf("can't create TX1 trie: %v", err))
   194  		}
   195  	}
   196  	return c.tx1Trie
   197  }
   198  
   199  func (self *stateObject) HasTX1(db Database, txHash common.Hash) bool {
   200  
   201  	_, ok := self.dirtyTX1[txHash]
   202  	if ok {
   203  		return true
   204  	}
   205  
   206  	enc, err := self.getTX1Trie(db).TryGet(txHash[:])
   207  	if err != nil {
   208  		return false
   209  	}
   210  	if len(enc) > 0 {
   211  		_, content, _, err := rlp.Split(enc)
   212  		if err != nil {
   213  			self.setError(err)
   214  			return false
   215  		}
   216  		if !bytes.Equal(content, txHash[:]) {
   217  			self.setError(fmt.Errorf("content mismatch the tx hash"))
   218  			return false
   219  		}
   220  
   221  		return true
   222  	}
   223  
   224  	return false
   225  }
   226  
   227  func (self *stateObject) AddTX1(db Database, txHash common.Hash) {
   228  	self.db.journal = append(self.db.journal, addTX1Change{
   229  		account: &self.address,
   230  		txHash:  txHash,
   231  	})
   232  	self.addTX1(txHash)
   233  }
   234  
   235  func (self *stateObject) addTX1(txHash common.Hash) {
   236  	self.dirtyTX1[txHash] = struct{}{}
   237  }
   238  
   239  func (self *stateObject) removeTX1(txHash common.Hash) {
   240  	delete(self.dirtyTX1, txHash)
   241  }
   242  
   243  func (self *stateObject) updateTX1Trie(db Database) Trie {
   244  	tr := self.getTX1Trie(db)
   245  
   246  	for tx1 := range self.dirtyTX1 {
   247  		delete(self.dirtyTX1, tx1)
   248  
   249  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(tx1[:], "\x00"))
   250  		self.setError(tr.TryUpdate(tx1[:], v))
   251  	}
   252  	return tr
   253  }
   254  
   255  func (self *stateObject) updateTX1Root(db Database) {
   256  	self.updateTX1Trie(db)
   257  	self.data.TX1Root = self.tx1Trie.Hash()
   258  }
   259  
   260  func (self *stateObject) CommitTX1Trie(db Database) error {
   261  	self.updateTX1Trie(db)
   262  	if self.dbErr != nil {
   263  		return self.dbErr
   264  	}
   265  	root, err := self.tx1Trie.Commit(nil)
   266  	if err == nil {
   267  		self.data.TX1Root = root
   268  	}
   269  	return err
   270  }
   271  
   272  func (c *stateObject) getTX3Trie(db Database) Trie {
   273  	if c.tx3Trie == nil {
   274  		var err error
   275  		c.tx3Trie, err = db.OpenTX3Trie(c.addrHash, c.data.TX3Root)
   276  		if err != nil {
   277  			c.tx3Trie, _ = db.OpenTX3Trie(c.addrHash, common.Hash{})
   278  			c.setError(fmt.Errorf("can't create TX3 trie: %v", err))
   279  		}
   280  	}
   281  	return c.tx3Trie
   282  }
   283  
   284  func (self *stateObject) HasTX3(db Database, txHash common.Hash) bool {
   285  
   286  	_, ok := self.dirtyTX3[txHash]
   287  	if ok {
   288  		return true
   289  	}
   290  
   291  	enc, err := self.getTX3Trie(db).TryGet(txHash[:])
   292  	if err != nil {
   293  		return false
   294  	}
   295  	if len(enc) > 0 {
   296  		_, content, _, err := rlp.Split(enc)
   297  		if err != nil {
   298  			self.setError(err)
   299  			return false
   300  		}
   301  		if !bytes.Equal(content, txHash[:]) {
   302  			self.setError(fmt.Errorf("content mismatch the tx hash"))
   303  			return false
   304  		}
   305  
   306  		return true
   307  	}
   308  
   309  	return false
   310  }
   311  
   312  func (self *stateObject) AddTX3(db Database, txHash common.Hash) {
   313  	self.db.journal = append(self.db.journal, addTX3Change{
   314  		account: &self.address,
   315  		txHash:  txHash,
   316  	})
   317  	self.addTX3(txHash)
   318  }
   319  
   320  func (self *stateObject) addTX3(txHash common.Hash) {
   321  	self.dirtyTX3[txHash] = struct{}{}
   322  }
   323  
   324  func (self *stateObject) removeTX3(txHash common.Hash) {
   325  	delete(self.dirtyTX3, txHash)
   326  }
   327  
   328  func (self *stateObject) updateTX3Trie(db Database) Trie {
   329  	tr := self.getTX3Trie(db)
   330  
   331  	for tx3 := range self.dirtyTX3 {
   332  		delete(self.dirtyTX3, tx3)
   333  
   334  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(tx3[:], "\x00"))
   335  		self.setError(tr.TryUpdate(tx3[:], v))
   336  	}
   337  	return tr
   338  }
   339  
   340  func (self *stateObject) updateTX3Root(db Database) {
   341  	self.updateTX3Trie(db)
   342  	self.data.TX3Root = self.tx3Trie.Hash()
   343  }
   344  
   345  func (self *stateObject) CommitTX3Trie(db Database) error {
   346  	self.updateTX3Trie(db)
   347  	if self.dbErr != nil {
   348  		return self.dbErr
   349  	}
   350  	root, err := self.tx3Trie.Commit(nil)
   351  	if err == nil {
   352  		self.data.TX3Root = root
   353  	}
   354  	return err
   355  }
   356  
   357  func (c *stateObject) getTrie(db Database) Trie {
   358  	if c.trie == nil {
   359  		var err error
   360  		c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root)
   361  		if err != nil {
   362  			c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{})
   363  			c.setError(fmt.Errorf("can't create storage trie: %v", err))
   364  		}
   365  	}
   366  	return c.trie
   367  }
   368  
   369  func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
   370  
   371  	value, dirty := self.dirtyStorage[key]
   372  	if dirty {
   373  		return value
   374  	}
   375  
   376  	return self.GetCommittedState(db, key)
   377  }
   378  
   379  func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash {
   380  
   381  	value, cached := self.originStorage[key]
   382  	if cached {
   383  		return value
   384  	}
   385  
   386  	enc, err := self.getTrie(db).TryGet(key[:])
   387  	if err != nil {
   388  		self.setError(err)
   389  		return common.Hash{}
   390  	}
   391  	if len(enc) > 0 {
   392  		_, content, _, err := rlp.Split(enc)
   393  		if err != nil {
   394  			self.setError(err)
   395  		}
   396  		value.SetBytes(content)
   397  	}
   398  	self.originStorage[key] = value
   399  	return value
   400  }
   401  
   402  func (self *stateObject) SetState(db Database, key, value common.Hash) {
   403  	self.db.journal = append(self.db.journal, storageChange{
   404  		account:  &self.address,
   405  		key:      key,
   406  		prevalue: self.GetState(db, key),
   407  	})
   408  	self.setState(key, value)
   409  }
   410  
   411  func (self *stateObject) setState(key, value common.Hash) {
   412  	self.dirtyStorage[key] = value
   413  
   414  	if self.onDirty != nil {
   415  		self.onDirty(self.Address())
   416  		self.onDirty = nil
   417  	}
   418  }
   419  
   420  func (self *stateObject) updateTrie(db Database) Trie {
   421  	tr := self.getTrie(db)
   422  	for key, value := range self.dirtyStorage {
   423  		delete(self.dirtyStorage, key)
   424  
   425  		if value == self.originStorage[key] {
   426  			continue
   427  		}
   428  		self.originStorage[key] = value
   429  
   430  		if (value == common.Hash{}) {
   431  			self.setError(tr.TryDelete(key[:]))
   432  			continue
   433  		}
   434  
   435  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
   436  		self.setError(tr.TryUpdate(key[:], v))
   437  	}
   438  	return tr
   439  }
   440  
   441  func (self *stateObject) updateRoot(db Database) {
   442  	self.updateTrie(db)
   443  	self.data.Root = self.trie.Hash()
   444  }
   445  
   446  func (self *stateObject) CommitTrie(db Database) error {
   447  	self.updateTrie(db)
   448  	if self.dbErr != nil {
   449  		return self.dbErr
   450  	}
   451  	root, err := self.trie.Commit(nil)
   452  	if err == nil {
   453  		self.data.Root = root
   454  	}
   455  	return err
   456  }
   457  
   458  func (c *stateObject) AddBalance(amount *big.Int) {
   459  
   460  	if amount.Sign() == 0 {
   461  		if c.empty() {
   462  			c.touch()
   463  		}
   464  
   465  		return
   466  	}
   467  	c.SetBalance(new(big.Int).Add(c.Balance(), amount))
   468  }
   469  
   470  func (c *stateObject) SubBalance(amount *big.Int) {
   471  	if amount.Sign() == 0 {
   472  		return
   473  	}
   474  	c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
   475  }
   476  
   477  func (self *stateObject) SetBalance(amount *big.Int) {
   478  	self.db.journal = append(self.db.journal, balanceChange{
   479  		account: &self.address,
   480  		prev:    new(big.Int).Set(self.data.Balance),
   481  	})
   482  	self.setBalance(amount)
   483  }
   484  
   485  func (self *stateObject) setBalance(amount *big.Int) {
   486  	self.data.Balance = amount
   487  	if self.onDirty != nil {
   488  		self.onDirty(self.Address())
   489  		self.onDirty = nil
   490  	}
   491  }
   492  
   493  func (c *stateObject) ReturnGas(gas *big.Int) {}
   494  
   495  func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject {
   496  	stateObject := newObject(db, self.address, self.data, onDirty)
   497  	if self.trie != nil {
   498  		stateObject.trie = db.db.CopyTrie(self.trie)
   499  	}
   500  	if self.tx1Trie != nil {
   501  		stateObject.tx1Trie = db.db.CopyTrie(self.tx1Trie)
   502  	}
   503  	if self.tx3Trie != nil {
   504  		stateObject.tx3Trie = db.db.CopyTrie(self.tx3Trie)
   505  	}
   506  	if self.proxiedTrie != nil {
   507  		stateObject.proxiedTrie = db.db.CopyTrie(self.proxiedTrie)
   508  	}
   509  	if self.rewardTrie != nil {
   510  		stateObject.rewardTrie = db.db.CopyTrie(self.rewardTrie)
   511  	}
   512  	stateObject.code = self.code
   513  	stateObject.dirtyStorage = self.dirtyStorage.Copy()
   514  	stateObject.originStorage = self.originStorage.Copy()
   515  	stateObject.suicided = self.suicided
   516  	stateObject.dirtyCode = self.dirtyCode
   517  	stateObject.deleted = self.deleted
   518  	stateObject.dirtyTX1 = make(map[common.Hash]struct{})
   519  	for tx1 := range self.dirtyTX1 {
   520  		stateObject.dirtyTX1[tx1] = struct{}{}
   521  	}
   522  	stateObject.dirtyTX3 = make(map[common.Hash]struct{})
   523  	for tx3 := range self.dirtyTX3 {
   524  		stateObject.dirtyTX3[tx3] = struct{}{}
   525  	}
   526  	stateObject.dirtyProxied = self.dirtyProxied.Copy()
   527  	stateObject.originProxied = self.originProxied.Copy()
   528  	stateObject.dirtyReward = self.dirtyReward.Copy()
   529  	stateObject.originReward = self.originReward.Copy()
   530  	return stateObject
   531  }
   532  
   533  func (c *stateObject) Address() common.Address {
   534  	return c.address
   535  }
   536  
   537  func (self *stateObject) Code(db Database) []byte {
   538  	if self.code != nil {
   539  		return self.code
   540  	}
   541  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   542  		return nil
   543  	}
   544  	code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   545  	if err != nil {
   546  		self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
   547  	}
   548  	self.code = code
   549  	return code
   550  }
   551  
   552  func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
   553  	prevcode := self.Code(self.db.db)
   554  	self.db.journal = append(self.db.journal, codeChange{
   555  		account:  &self.address,
   556  		prevhash: self.CodeHash(),
   557  		prevcode: prevcode,
   558  	})
   559  	self.setCode(codeHash, code)
   560  }
   561  
   562  func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
   563  	self.code = code
   564  	self.data.CodeHash = codeHash[:]
   565  	self.dirtyCode = true
   566  	if self.onDirty != nil {
   567  		self.onDirty(self.Address())
   568  		self.onDirty = nil
   569  	}
   570  }
   571  
   572  func (self *stateObject) SetNonce(nonce uint64) {
   573  	self.db.journal = append(self.db.journal, nonceChange{
   574  		account: &self.address,
   575  		prev:    self.data.Nonce,
   576  	})
   577  	self.setNonce(nonce)
   578  }
   579  
   580  func (self *stateObject) setNonce(nonce uint64) {
   581  	self.data.Nonce = nonce
   582  	if self.onDirty != nil {
   583  		self.onDirty(self.Address())
   584  		self.onDirty = nil
   585  	}
   586  }
   587  
   588  func (self *stateObject) CodeHash() []byte {
   589  	return self.data.CodeHash
   590  }
   591  
   592  func (self *stateObject) Balance() *big.Int {
   593  	return self.data.Balance
   594  }
   595  
   596  func (self *stateObject) Nonce() uint64 {
   597  	return self.data.Nonce
   598  }
   599  
   600  func (self *stateObject) Value() *big.Int {
   601  	panic("Value on stateObject should never be called")
   602  }
   603  
   604  func (self *stateObject) SetAddress(address common.Address) {
   605  	self.db.journal = append(self.db.journal, fAddressChange{
   606  		account: &self.address,
   607  		prev:    self.data.FAddress,
   608  	})
   609  
   610  	self.setAddress(address)
   611  }
   612  
   613  func (self *stateObject) setAddress(address common.Address) {
   614  	self.data.FAddress = address
   615  	if self.onDirty != nil {
   616  		self.onDirty(self.Address())
   617  		self.onDirty = nil
   618  	}
   619  }
   620  
   621  func (self *stateObject) GetAddress() common.Address {
   622  	return self.data.FAddress
   623  }