github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/core/state/state_object.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:34</date>
    10  //</624342618179899392>
    11  
    12  
    13  package state
    14  
    15  import (
    16  	"bytes"
    17  	"fmt"
    18  	"io"
    19  	"math/big"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/ethereum/go-ethereum/crypto"
    23  	"github.com/ethereum/go-ethereum/rlp"
    24  )
    25  
    26  var emptyCodeHash = crypto.Keccak256(nil)
    27  
    28  type Code []byte
    29  
    30  func (self Code) String() string {
    31  return string(self) //strings.join(反汇编(self),“”)
    32  }
    33  
    34  type Storage map[common.Hash]common.Hash
    35  
    36  func (self Storage) String() (str string) {
    37  	for key, value := range self {
    38  		str += fmt.Sprintf("%X : %X\n", key, value)
    39  	}
    40  
    41  	return
    42  }
    43  
    44  func (self Storage) Copy() Storage {
    45  	cpy := make(Storage)
    46  	for key, value := range self {
    47  		cpy[key] = value
    48  	}
    49  
    50  	return cpy
    51  }
    52  
    53  //StateObject表示正在修改的以太坊帐户。
    54  //
    55  //使用模式如下:
    56  //首先需要获取一个状态对象。
    57  //可以通过对象访问和修改帐户值。
    58  //最后,调用committrie将修改后的存储trie写入数据库。
    59  type stateObject struct {
    60  	address  common.Address
    61  addrHash common.Hash //帐户的以太坊地址哈希
    62  	data     Account
    63  	db       *StateDB
    64  
    65  //数据库错误。
    66  //状态对象由共识核心和虚拟机使用,它们是
    67  //无法处理数据库级错误。发生的任何错误
    68  //在数据库读取过程中,将在此处记忆并最终返回
    69  //按statedb.commit。
    70  	dbErr error
    71  
    72  //编写高速缓存。
    73  trie Trie //存储trie,在第一次访问时变为非nil
    74  code Code //契约字节码,在加载代码时设置
    75  
    76  cachedStorage Storage //存储项缓存以避免重复读取
    77  dirtyStorage  Storage //需要刷新到磁盘的存储项
    78  
    79  //缓存标志。
    80  //当一个对象被标记为自杀时,它将从trie中删除。
    81  //在状态转换的“更新”阶段。
    82  dirtyCode bool //如果代码已更新,则为true
    83  	suicided  bool
    84  	deleted   bool
    85  }
    86  
    87  //empty返回帐户是否被视为空。
    88  func (s *stateObject) empty() bool {
    89  	return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
    90  }
    91  
    92  //账户是账户的以太坊共识代表。
    93  //这些对象存储在主帐户trie中。
    94  type Account struct {
    95  	Nonce    uint64
    96  	Balance  *big.Int
    97  Root     common.Hash //存储树的merkle根
    98  	CodeHash []byte
    99  }
   100  
   101  //NewObject创建一个状态对象。
   102  func newObject(db *StateDB, address common.Address, data Account) *stateObject {
   103  	if data.Balance == nil {
   104  		data.Balance = new(big.Int)
   105  	}
   106  	if data.CodeHash == nil {
   107  		data.CodeHash = emptyCodeHash
   108  	}
   109  	return &stateObject{
   110  		db:            db,
   111  		address:       address,
   112  		addrHash:      crypto.Keccak256Hash(address[:]),
   113  		data:          data,
   114  		cachedStorage: make(Storage),
   115  		dirtyStorage:  make(Storage),
   116  	}
   117  }
   118  
   119  //encoderlp实现rlp.encoder。
   120  func (c *stateObject) EncodeRLP(w io.Writer) error {
   121  	return rlp.Encode(w, c.data)
   122  }
   123  
   124  //setError记住调用它时使用的第一个非零错误。
   125  func (self *stateObject) setError(err error) {
   126  	if self.dbErr == nil {
   127  		self.dbErr = err
   128  	}
   129  }
   130  
   131  func (self *stateObject) markSuicided() {
   132  	self.suicided = true
   133  }
   134  
   135  func (c *stateObject) touch() {
   136  	c.db.journal.append(touchChange{
   137  		account: &c.address,
   138  	})
   139  	if c.address == ripemd {
   140  //显式地将其放入脏缓存中,否则将从
   141  //扁平轴颈。
   142  		c.db.journal.dirty(c.address)
   143  	}
   144  }
   145  
   146  func (c *stateObject) getTrie(db Database) Trie {
   147  	if c.trie == nil {
   148  		var err error
   149  		c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root)
   150  		if err != nil {
   151  			c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{})
   152  			c.setError(fmt.Errorf("can't create storage trie: %v", err))
   153  		}
   154  	}
   155  	return c.trie
   156  }
   157  
   158  //GetState返回帐户存储中的值。
   159  func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
   160  	value, exists := self.cachedStorage[key]
   161  	if exists {
   162  		return value
   163  	}
   164  //从数据库加载以防丢失。
   165  	enc, err := self.getTrie(db).TryGet(key[:])
   166  	if err != nil {
   167  		self.setError(err)
   168  		return common.Hash{}
   169  	}
   170  	if len(enc) > 0 {
   171  		_, content, _, err := rlp.Split(enc)
   172  		if err != nil {
   173  			self.setError(err)
   174  		}
   175  		value.SetBytes(content)
   176  	}
   177  	self.cachedStorage[key] = value
   178  	return value
   179  }
   180  
   181  //setstate更新帐户存储中的值。
   182  func (self *stateObject) SetState(db Database, key, value common.Hash) {
   183  	self.db.journal.append(storageChange{
   184  		account:  &self.address,
   185  		key:      key,
   186  		prevalue: self.GetState(db, key),
   187  	})
   188  	self.setState(key, value)
   189  }
   190  
   191  func (self *stateObject) setState(key, value common.Hash) {
   192  	self.cachedStorage[key] = value
   193  	self.dirtyStorage[key] = value
   194  }
   195  
   196  //updatetrie将缓存的存储修改写入对象的存储trie。
   197  func (self *stateObject) updateTrie(db Database) Trie {
   198  	tr := self.getTrie(db)
   199  	for key, value := range self.dirtyStorage {
   200  		delete(self.dirtyStorage, key)
   201  		if (value == common.Hash{}) {
   202  			self.setError(tr.TryDelete(key[:]))
   203  			continue
   204  		}
   205  //编码[]字节不能失败,可以忽略错误。
   206  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
   207  		self.setError(tr.TryUpdate(key[:], v))
   208  	}
   209  	return tr
   210  }
   211  
   212  //updateRoot将trie根设置为当前根哈希
   213  func (self *stateObject) updateRoot(db Database) {
   214  	self.updateTrie(db)
   215  	self.data.Root = self.trie.Hash()
   216  }
   217  
   218  //将对象的存储trie提交给db。
   219  //这将更新trie根目录。
   220  func (self *stateObject) CommitTrie(db Database) error {
   221  	self.updateTrie(db)
   222  	if self.dbErr != nil {
   223  		return self.dbErr
   224  	}
   225  	root, err := self.trie.Commit(nil)
   226  	if err == nil {
   227  		self.data.Root = root
   228  	}
   229  	return err
   230  }
   231  
   232  //AddBalance从C的余额中删除金额。
   233  //它用于将资金添加到转账的目的地帐户。
   234  func (c *stateObject) AddBalance(amount *big.Int) {
   235  //EIP158:我们必须检查对象的空性,以便帐户
   236  //清除(0,0,0个对象)可以生效。
   237  	if amount.Sign() == 0 {
   238  		if c.empty() {
   239  			c.touch()
   240  		}
   241  
   242  		return
   243  	}
   244  	c.SetBalance(new(big.Int).Add(c.Balance(), amount))
   245  }
   246  
   247  //次平衡从C的平衡中除去了数量。
   248  //它用于从转账的原始账户中取出资金。
   249  func (c *stateObject) SubBalance(amount *big.Int) {
   250  	if amount.Sign() == 0 {
   251  		return
   252  	}
   253  	c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
   254  }
   255  
   256  func (self *stateObject) SetBalance(amount *big.Int) {
   257  	self.db.journal.append(balanceChange{
   258  		account: &self.address,
   259  		prev:    new(big.Int).Set(self.data.Balance),
   260  	})
   261  	self.setBalance(amount)
   262  }
   263  
   264  func (self *stateObject) setBalance(amount *big.Int) {
   265  	self.data.Balance = amount
   266  }
   267  
   268  //将气体返回原点。由虚拟机或闭包使用
   269  func (c *stateObject) ReturnGas(gas *big.Int) {}
   270  
   271  func (self *stateObject) deepCopy(db *StateDB) *stateObject {
   272  	stateObject := newObject(db, self.address, self.data)
   273  	if self.trie != nil {
   274  		stateObject.trie = db.db.CopyTrie(self.trie)
   275  	}
   276  	stateObject.code = self.code
   277  	stateObject.dirtyStorage = self.dirtyStorage.Copy()
   278  	stateObject.cachedStorage = self.dirtyStorage.Copy()
   279  	stateObject.suicided = self.suicided
   280  	stateObject.dirtyCode = self.dirtyCode
   281  	stateObject.deleted = self.deleted
   282  	return stateObject
   283  }
   284  
   285  //
   286  //属性访问器
   287  //
   288  
   289  //返回合同/帐户的地址
   290  func (c *stateObject) Address() common.Address {
   291  	return c.address
   292  }
   293  
   294  //代码返回与此对象关联的合同代码(如果有)。
   295  func (self *stateObject) Code(db Database) []byte {
   296  	if self.code != nil {
   297  		return self.code
   298  	}
   299  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   300  		return nil
   301  	}
   302  	code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   303  	if err != nil {
   304  		self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
   305  	}
   306  	self.code = code
   307  	return code
   308  }
   309  
   310  func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
   311  	prevcode := self.Code(self.db.db)
   312  	self.db.journal.append(codeChange{
   313  		account:  &self.address,
   314  		prevhash: self.CodeHash(),
   315  		prevcode: prevcode,
   316  	})
   317  	self.setCode(codeHash, code)
   318  }
   319  
   320  func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
   321  	self.code = code
   322  	self.data.CodeHash = codeHash[:]
   323  	self.dirtyCode = true
   324  }
   325  
   326  func (self *stateObject) SetNonce(nonce uint64) {
   327  	self.db.journal.append(nonceChange{
   328  		account: &self.address,
   329  		prev:    self.data.Nonce,
   330  	})
   331  	self.setNonce(nonce)
   332  }
   333  
   334  func (self *stateObject) setNonce(nonce uint64) {
   335  	self.data.Nonce = nonce
   336  }
   337  
   338  func (self *stateObject) CodeHash() []byte {
   339  	return self.data.CodeHash
   340  }
   341  
   342  func (self *stateObject) Balance() *big.Int {
   343  	return self.data.Balance
   344  }
   345  
   346  func (self *stateObject) Nonce() uint64 {
   347  	return self.data.Nonce
   348  }
   349  
   350  //从未调用,但必须存在才能使用StateObject
   351  //作为一个也满足vm.contractRef的vm.account接口
   352  //接口。界面很棒。
   353  func (self *stateObject) Value() *big.Int {
   354  	panic("Value on stateObject should never be called")
   355  }
   356