github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:35</date>
    10  //</624450080396546048>
    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  originStorage Storage //Storage cache of original entries to dedup rewrites
    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 root of the storage trie
    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  		originStorage: 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  //如果此状态项有一个脏值,请返回它
   161  	value, dirty := self.dirtyStorage[key]
   162  	if dirty {
   163  		return value
   164  	}
   165  //否则返回条目的原始值
   166  	return self.GetCommittedState(db, key)
   167  }
   168  
   169  //getcommittedState从提交的帐户存储trie中检索值。
   170  func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash {
   171  //如果缓存了原始值,则返回
   172  	value, cached := self.originStorage[key]
   173  	if cached {
   174  		return value
   175  	}
   176  //否则从数据库加载值
   177  	enc, err := self.getTrie(db).TryGet(key[:])
   178  	if err != nil {
   179  		self.setError(err)
   180  		return common.Hash{}
   181  	}
   182  	if len(enc) > 0 {
   183  		_, content, _, err := rlp.Split(enc)
   184  		if err != nil {
   185  			self.setError(err)
   186  		}
   187  		value.SetBytes(content)
   188  	}
   189  	self.originStorage[key] = value
   190  	return value
   191  }
   192  
   193  //setstate更新帐户存储中的值。
   194  func (self *stateObject) SetState(db Database, key, value common.Hash) {
   195  //如果新值与旧值相同,则不要设置
   196  	prev := self.GetState(db, key)
   197  	if prev == value {
   198  		return
   199  	}
   200  //新值不同,更新并记录更改
   201  	self.db.journal.append(storageChange{
   202  		account:  &self.address,
   203  		key:      key,
   204  		prevalue: prev,
   205  	})
   206  	self.setState(key, value)
   207  }
   208  
   209  func (self *stateObject) setState(key, value common.Hash) {
   210  	self.dirtyStorage[key] = value
   211  }
   212  
   213  //updatetrie将缓存的存储修改写入对象的存储trie。
   214  func (self *stateObject) updateTrie(db Database) Trie {
   215  	tr := self.getTrie(db)
   216  	for key, value := range self.dirtyStorage {
   217  		delete(self.dirtyStorage, key)
   218  
   219  //跳过noop更改,保留实际更改
   220  		if value == self.originStorage[key] {
   221  			continue
   222  		}
   223  		self.originStorage[key] = value
   224  
   225  		if (value == common.Hash{}) {
   226  			self.setError(tr.TryDelete(key[:]))
   227  			continue
   228  		}
   229  //编码[]字节不能失败,可以忽略错误。
   230  		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
   231  		self.setError(tr.TryUpdate(key[:], v))
   232  	}
   233  	return tr
   234  }
   235  
   236  //UpdateRoot sets the trie root to the current root hash of
   237  func (self *stateObject) updateRoot(db Database) {
   238  	self.updateTrie(db)
   239  	self.data.Root = self.trie.Hash()
   240  }
   241  
   242  //将对象的存储trie提交给db。
   243  //这将更新trie根目录。
   244  func (self *stateObject) CommitTrie(db Database) error {
   245  	self.updateTrie(db)
   246  	if self.dbErr != nil {
   247  		return self.dbErr
   248  	}
   249  	root, err := self.trie.Commit(nil)
   250  	if err == nil {
   251  		self.data.Root = root
   252  	}
   253  	return err
   254  }
   255  
   256  //AddBalance从C的余额中删除金额。
   257  //它用于将资金添加到转账的目的地帐户。
   258  func (c *stateObject) AddBalance(amount *big.Int) {
   259  //EIP158:我们必须检查对象的空性,以便帐户
   260  //清除(0,0,0个对象)可以生效。
   261  	if amount.Sign() == 0 {
   262  		if c.empty() {
   263  			c.touch()
   264  		}
   265  
   266  		return
   267  	}
   268  	c.SetBalance(new(big.Int).Add(c.Balance(), amount))
   269  }
   270  
   271  //次平衡从C的平衡中除去了数量。
   272  //它用于从转账的原始账户中取出资金。
   273  func (c *stateObject) SubBalance(amount *big.Int) {
   274  	if amount.Sign() == 0 {
   275  		return
   276  	}
   277  	c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
   278  }
   279  
   280  func (self *stateObject) SetBalance(amount *big.Int) {
   281  	self.db.journal.append(balanceChange{
   282  		account: &self.address,
   283  		prev:    new(big.Int).Set(self.data.Balance),
   284  	})
   285  	self.setBalance(amount)
   286  }
   287  
   288  func (self *stateObject) setBalance(amount *big.Int) {
   289  	self.data.Balance = amount
   290  }
   291  
   292  //将气体返回原点。由虚拟机或闭包使用
   293  func (c *stateObject) ReturnGas(gas *big.Int) {}
   294  
   295  func (self *stateObject) deepCopy(db *StateDB) *stateObject {
   296  	stateObject := newObject(db, self.address, self.data)
   297  	if self.trie != nil {
   298  		stateObject.trie = db.db.CopyTrie(self.trie)
   299  	}
   300  	stateObject.code = self.code
   301  	stateObject.dirtyStorage = self.dirtyStorage.Copy()
   302  	stateObject.originStorage = self.originStorage.Copy()
   303  	stateObject.suicided = self.suicided
   304  	stateObject.dirtyCode = self.dirtyCode
   305  	stateObject.deleted = self.deleted
   306  	return stateObject
   307  }
   308  
   309  //
   310  //属性访问器
   311  //
   312  
   313  //返回合同/帐户的地址
   314  func (c *stateObject) Address() common.Address {
   315  	return c.address
   316  }
   317  
   318  //代码返回与此对象关联的合同代码(如果有)。
   319  func (self *stateObject) Code(db Database) []byte {
   320  	if self.code != nil {
   321  		return self.code
   322  	}
   323  	if bytes.Equal(self.CodeHash(), emptyCodeHash) {
   324  		return nil
   325  	}
   326  	code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash()))
   327  	if err != nil {
   328  		self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
   329  	}
   330  	self.code = code
   331  	return code
   332  }
   333  
   334  func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
   335  	prevcode := self.Code(self.db.db)
   336  	self.db.journal.append(codeChange{
   337  		account:  &self.address,
   338  		prevhash: self.CodeHash(),
   339  		prevcode: prevcode,
   340  	})
   341  	self.setCode(codeHash, code)
   342  }
   343  
   344  func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
   345  	self.code = code
   346  	self.data.CodeHash = codeHash[:]
   347  	self.dirtyCode = true
   348  }
   349  
   350  func (self *stateObject) SetNonce(nonce uint64) {
   351  	self.db.journal.append(nonceChange{
   352  		account: &self.address,
   353  		prev:    self.data.Nonce,
   354  	})
   355  	self.setNonce(nonce)
   356  }
   357  
   358  func (self *stateObject) setNonce(nonce uint64) {
   359  	self.data.Nonce = nonce
   360  }
   361  
   362  func (self *stateObject) CodeHash() []byte {
   363  	return self.data.CodeHash
   364  }
   365  
   366  func (self *stateObject) Balance() *big.Int {
   367  	return self.data.Balance
   368  }
   369  
   370  func (self *stateObject) Nonce() uint64 {
   371  	return self.data.Nonce
   372  }
   373  
   374  //从未调用,但必须存在才能使用StateObject
   375  //作为一个也满足vm.contractRef的vm.account接口
   376  //接口。界面很棒。
   377  func (self *stateObject) Value() *big.Int {
   378  	panic("Value on stateObject should never be called")
   379  }
   380