github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/consensus/clique/snapshot.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:34</date>
    10  //</624450074558074880>
    11  
    12  
    13  package clique
    14  
    15  import (
    16  	"bytes"
    17  	"encoding/json"
    18  	"sort"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/core/types"
    22  	"github.com/ethereum/go-ethereum/ethdb"
    23  	"github.com/ethereum/go-ethereum/params"
    24  	lru "github.com/hashicorp/golang-lru"
    25  )
    26  
    27  //投票代表授权签名人修改
    28  //授权列表。
    29  type Vote struct {
    30  Signer    common.Address `json:"signer"`    //投票的授权签署人
    31  Block     uint64         `json:"block"`     //投票所投的区号(过期旧票)
    32  Address   common.Address `json:"address"`   //正在投票更改其授权的帐户
    33  Authorize bool           `json:"authorize"` //是否授权或取消对投票帐户的授权
    34  }
    35  
    36  //计票是一种简单的计票方式,用来保持当前的计票结果。投票赞成
    37  //反对这项提议并不算在内,因为它等同于不投票。
    38  type Tally struct {
    39  Authorize bool `json:"authorize"` //投票是授权还是踢某人
    40  Votes     int  `json:"votes"`     //到目前为止想要通过提案的票数
    41  }
    42  
    43  //快照是在给定时间点上投票的授权状态。
    44  type Snapshot struct {
    45  config   *params.CliqueConfig //微调行为的一致引擎参数
    46  sigcache *lru.ARCCache        //缓存最近的块签名以加快ecrecover
    47  
    48  Number  uint64                      `json:"number"`  //创建快照的块号
    49  Hash    common.Hash                 `json:"hash"`    //创建快照的块哈希
    50  Signers map[common.Address]struct{} `json:"signers"` //此时的授权签名人集合
    51  Recents map[uint64]common.Address   `json:"recents"` //垃圾邮件保护的最近签名者集
    52  Votes   []*Vote                     `json:"votes"`   //按时间顺序投票的名单
    53  Tally   map[common.Address]Tally    `json:"tally"`   //当前投票计数以避免重新计算
    54  }
    55  
    56  //SignerAscending实现排序接口,以允许对地址列表进行排序
    57  type signersAscending []common.Address
    58  
    59  func (s signersAscending) Len() int           { return len(s) }
    60  func (s signersAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 }
    61  func (s signersAscending) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
    62  
    63  //NewSnapshot使用指定的启动参数创建新快照。这个
    64  //方法不初始化最近的签名者集,因此仅当用于
    65  //创世纪板块。
    66  func newSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot {
    67  	snap := &Snapshot{
    68  		config:   config,
    69  		sigcache: sigcache,
    70  		Number:   number,
    71  		Hash:     hash,
    72  		Signers:  make(map[common.Address]struct{}),
    73  		Recents:  make(map[uint64]common.Address),
    74  		Tally:    make(map[common.Address]Tally),
    75  	}
    76  	for _, signer := range signers {
    77  		snap.Signers[signer] = struct{}{}
    78  	}
    79  	return snap
    80  }
    81  
    82  //LoadSnapshot从数据库加载现有快照。
    83  func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
    84  	blob, err := db.Get(append([]byte("clique-"), hash[:]...))
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	snap := new(Snapshot)
    89  	if err := json.Unmarshal(blob, snap); err != nil {
    90  		return nil, err
    91  	}
    92  	snap.config = config
    93  	snap.sigcache = sigcache
    94  
    95  	return snap, nil
    96  }
    97  
    98  //存储将快照插入数据库。
    99  func (s *Snapshot) store(db ethdb.Database) error {
   100  	blob, err := json.Marshal(s)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return db.Put(append([]byte("clique-"), s.Hash[:]...), blob)
   105  }
   106  
   107  //复制创建快照的深度副本,尽管不是单个投票。
   108  func (s *Snapshot) copy() *Snapshot {
   109  	cpy := &Snapshot{
   110  		config:   s.config,
   111  		sigcache: s.sigcache,
   112  		Number:   s.Number,
   113  		Hash:     s.Hash,
   114  		Signers:  make(map[common.Address]struct{}),
   115  		Recents:  make(map[uint64]common.Address),
   116  		Votes:    make([]*Vote, len(s.Votes)),
   117  		Tally:    make(map[common.Address]Tally),
   118  	}
   119  	for signer := range s.Signers {
   120  		cpy.Signers[signer] = struct{}{}
   121  	}
   122  	for block, signer := range s.Recents {
   123  		cpy.Recents[block] = signer
   124  	}
   125  	for address, tally := range s.Tally {
   126  		cpy.Tally[address] = tally
   127  	}
   128  	copy(cpy.Votes, s.Votes)
   129  
   130  	return cpy
   131  }
   132  
   133  //validvote返回在
   134  //给定快照上下文(例如,不要尝试添加已授权的签名者)。
   135  func (s *Snapshot) validVote(address common.Address, authorize bool) bool {
   136  	_, signer := s.Signers[address]
   137  	return (signer && !authorize) || (!signer && authorize)
   138  }
   139  
   140  //Cast在计票中添加了新的选票。
   141  func (s *Snapshot) cast(address common.Address, authorize bool) bool {
   142  //确保投票有意义
   143  	if !s.validVote(address, authorize) {
   144  		return false
   145  	}
   146  //将投票投到现有或新的计票中
   147  	if old, ok := s.Tally[address]; ok {
   148  		old.Votes++
   149  		s.Tally[address] = old
   150  	} else {
   151  		s.Tally[address] = Tally{Authorize: authorize, Votes: 1}
   152  	}
   153  	return true
   154  }
   155  
   156  //uncast从计票中删除先前的投票。
   157  func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
   158  //如果没有计票结果,那是悬而未决的投票,就投吧。
   159  	tally, ok := s.Tally[address]
   160  	if !ok {
   161  		return false
   162  	}
   163  //确保我们只还原已计数的投票
   164  	if tally.Authorize != authorize {
   165  		return false
   166  	}
   167  //否则恢复投票
   168  	if tally.Votes > 1 {
   169  		tally.Votes--
   170  		s.Tally[address] = tally
   171  	} else {
   172  		delete(s.Tally, address)
   173  	}
   174  	return true
   175  }
   176  
   177  //应用通过将给定的头应用于创建新的授权快照
   178  //原来的那个。
   179  func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
   180  //不允许传入清除器代码的头
   181  	if len(headers) == 0 {
   182  		return s, nil
   183  	}
   184  //健全性检查标题是否可以应用
   185  	for i := 0; i < len(headers)-1; i++ {
   186  		if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 {
   187  			return nil, errInvalidVotingChain
   188  		}
   189  	}
   190  	if headers[0].Number.Uint64() != s.Number+1 {
   191  		return nil, errInvalidVotingChain
   192  	}
   193  //遍历头并创建新快照
   194  	snap := s.copy()
   195  
   196  	for _, header := range headers {
   197  //删除检查点块上的所有投票
   198  		number := header.Number.Uint64()
   199  		if number%s.config.Epoch == 0 {
   200  			snap.Votes = nil
   201  			snap.Tally = make(map[common.Address]Tally)
   202  		}
   203  //从最近列表中删除最早的签名者,以允许其再次签名。
   204  		if limit := uint64(len(snap.Signers)/2 + 1); number >= limit {
   205  			delete(snap.Recents, number-limit)
   206  		}
   207  //解析授权密钥并检查签名者
   208  		signer, err := ecrecover(header, s.sigcache)
   209  		if err != nil {
   210  			return nil, err
   211  		}
   212  		if _, ok := snap.Signers[signer]; !ok {
   213  			return nil, errUnauthorizedSigner
   214  		}
   215  		for _, recent := range snap.Recents {
   216  			if recent == signer {
   217  				return nil, errRecentlySigned
   218  			}
   219  		}
   220  		snap.Recents[number] = signer
   221  
   222  //标题已授权,放弃签名者以前的任何投票
   223  		for i, vote := range snap.Votes {
   224  			if vote.Signer == signer && vote.Address == header.Coinbase {
   225  //从缓存的计数中取消投票
   226  				snap.uncast(vote.Address, vote.Authorize)
   227  
   228  //取消按时间顺序排列的投票
   229  				snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   230  break //只允许一票
   231  			}
   232  		}
   233  //统计签名者的新投票
   234  		var authorize bool
   235  		switch {
   236  		case bytes.Equal(header.Nonce[:], nonceAuthVote):
   237  			authorize = true
   238  		case bytes.Equal(header.Nonce[:], nonceDropVote):
   239  			authorize = false
   240  		default:
   241  			return nil, errInvalidVote
   242  		}
   243  		if snap.cast(header.Coinbase, authorize) {
   244  			snap.Votes = append(snap.Votes, &Vote{
   245  				Signer:    signer,
   246  				Block:     number,
   247  				Address:   header.Coinbase,
   248  				Authorize: authorize,
   249  			})
   250  		}
   251  //如果投票通过,则更新签名者列表
   252  		if tally := snap.Tally[header.Coinbase]; tally.Votes > len(snap.Signers)/2 {
   253  			if tally.Authorize {
   254  				snap.Signers[header.Coinbase] = struct{}{}
   255  			} else {
   256  				delete(snap.Signers, header.Coinbase)
   257  
   258  //签名者列表收缩,删除所有剩余的最近缓存
   259  				if limit := uint64(len(snap.Signers)/2 + 1); number >= limit {
   260  					delete(snap.Recents, number-limit)
   261  				}
   262  //放弃取消授权签名者所投的任何以前的票
   263  				for i := 0; i < len(snap.Votes); i++ {
   264  					if snap.Votes[i].Signer == header.Coinbase {
   265  //从缓存的计数中取消投票
   266  						snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize)
   267  
   268  //取消按时间顺序排列的投票
   269  						snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   270  
   271  						i--
   272  					}
   273  				}
   274  			}
   275  //放弃对刚刚更改的帐户的任何以前的投票
   276  			for i := 0; i < len(snap.Votes); i++ {
   277  				if snap.Votes[i].Address == header.Coinbase {
   278  					snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   279  					i--
   280  				}
   281  			}
   282  			delete(snap.Tally, header.Coinbase)
   283  		}
   284  	}
   285  	snap.Number += uint64(len(headers))
   286  	snap.Hash = headers[len(headers)-1].Hash()
   287  
   288  	return snap, nil
   289  }
   290  
   291  //签名者按升序检索授权签名者列表。
   292  func (s *Snapshot) signers() []common.Address {
   293  	sigs := make([]common.Address, 0, len(s.Signers))
   294  	for sig := range s.Signers {
   295  		sigs = append(sigs, sig)
   296  	}
   297  	sort.Sort(signersAscending(sigs))
   298  	return sigs
   299  }
   300  
   301  //如果给定块高度的签名者依次是或不是,则Inturn返回。
   302  func (s *Snapshot) inturn(number uint64, signer common.Address) bool {
   303  	signers, offset := s.signers(), 0
   304  	for offset < len(signers) && signers[offset] != signer {
   305  		offset++
   306  	}
   307  	return (number % uint64(len(signers))) == uint64(offset)
   308  }
   309