github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/peer.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package eth
    26  
    27  import (
    28  	"errors"
    29  	"fmt"
    30  	"math/big"
    31  	"sync"
    32  	"time"
    33  
    34  	mapset "github.com/deckarep/golang-set"
    35  	"github.com/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/core/types"
    37  	"github.com/ethereum/go-ethereum/p2p"
    38  	"github.com/ethereum/go-ethereum/rlp"
    39  )
    40  
    41  
    42  
    43  var (
    44  	errClosed            = errors.New("peer set is closed")
    45  	errAlreadyRegistered = errors.New("peer is already registered")
    46  	errNotRegistered     = errors.New("peer is not registered")
    47  )
    48  
    49  const (
    50  maxKnownTxs    = 32768 //要保留在已知列表中的最大事务哈希数(防止DOS)
    51  maxKnownBlocks = 1024  //要保留在已知列表中的最大块哈希数(防止DOS)
    52  
    53  //maxqueuedtxs是要在之前排队的事务列表的最大数目
    54  //正在删除广播。这是一个敏感的数字,因为事务列表可能
    55  //包含一个或数千个事务。
    56  	maxQueuedTxs = 128
    57  
    58  //MaxQueuedProps是在之前排队的最大块传播数
    59  //正在删除广播。排队的陈旧街区没什么意义,所以有一些
    60  //这可能足以覆盖叔叔们。
    61  	maxQueuedProps = 4
    62  
    63  //MaxQueuedanns是要在之前排队的最大块通知数
    64  //正在删除广播。与块传播类似,没有排队点
    65  //超过一些健康的叔叔限制,所以使用。
    66  	maxQueuedAnns = 4
    67  
    68  	handshakeTimeout = 5 * time.Second
    69  )
    70  
    71  //PeerInfo表示已知以太坊子协议元数据的简短摘要
    72  //关于连接的对等机。
    73  type PeerInfo struct {
    74  Version    int      `json:"version"`    //已协商以太坊协议版本
    75  Difficulty *big.Int `json:"difficulty"` //同行区块链的总难度
    76  Head       string   `json:"head"`       //对等机最好拥有的块的sha3哈希
    77  }
    78  
    79  //propevent是一个块传播,在广播队列中等待它的循环。
    80  type propEvent struct {
    81  	block *types.Block
    82  	td    *big.Int
    83  }
    84  
    85  type peer struct {
    86  	id string
    87  
    88  	*p2p.Peer
    89  	rw p2p.MsgReadWriter
    90  
    91  version  int         //协议版本协商
    92  forkDrop *time.Timer //如果未及时验证分叉,则为定时连接滴管
    93  
    94  	head common.Hash
    95  	td   *big.Int
    96  	lock sync.RWMutex
    97  
    98  knownTxs    mapset.Set                //此对等方已知的事务哈希集
    99  knownBlocks mapset.Set                //此对等方已知的块哈希集
   100  queuedTxs   chan []*types.Transaction //要广播到对等机的事务队列
   101  queuedProps chan *propEvent           //向对等机广播的块队列
   102  queuedAnns  chan *types.Block         //向对等机宣布的块队列
   103  term        chan struct{}             //终止频道以停止广播
   104  }
   105  
   106  func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
   107  	return &peer{
   108  		Peer:        p,
   109  		rw:          rw,
   110  		version:     version,
   111  		id:          fmt.Sprintf("%x", p.ID().Bytes()[:8]),
   112  		knownTxs:    mapset.NewSet(),
   113  		knownBlocks: mapset.NewSet(),
   114  		queuedTxs:   make(chan []*types.Transaction, maxQueuedTxs),
   115  		queuedProps: make(chan *propEvent, maxQueuedProps),
   116  		queuedAnns:  make(chan *types.Block, maxQueuedAnns),
   117  		term:        make(chan struct{}),
   118  	}
   119  }
   120  
   121  //广播是一个写循环,它多路复用块传播、通知
   122  //事务广播到远程对等机。目标是要有一个异步
   123  //不锁定节点内部的编写器。
   124  func (p *peer) broadcast() {
   125  	for {
   126  		select {
   127  		case txs := <-p.queuedTxs:
   128  			if err := p.SendTransactions(txs); err != nil {
   129  				return
   130  			}
   131  			p.Log().Trace("Broadcast transactions", "count", len(txs))
   132  
   133  		case prop := <-p.queuedProps:
   134  			if err := p.SendNewBlock(prop.block, prop.td); err != nil {
   135  				return
   136  			}
   137  			p.Log().Trace("Propagated block", "number", prop.block.Number(), "hash", prop.block.Hash(), "td", prop.td)
   138  
   139  		case block := <-p.queuedAnns:
   140  			if err := p.SendNewBlockHashes([]common.Hash{block.Hash()}, []uint64{block.NumberU64()}); err != nil {
   141  				return
   142  			}
   143  			p.Log().Trace("Announced block", "number", block.Number(), "hash", block.Hash())
   144  
   145  		case <-p.term:
   146  			return
   147  		}
   148  	}
   149  }
   150  
   151  //关闭向广播线路发出终止信号。
   152  func (p *peer) close() {
   153  	close(p.term)
   154  }
   155  
   156  //INFO收集并返回有关对等机的已知元数据集合。
   157  func (p *peer) Info() *PeerInfo {
   158  	hash, td := p.Head()
   159  
   160  	return &PeerInfo{
   161  		Version:    p.version,
   162  		Difficulty: td,
   163  		Head:       hash.Hex(),
   164  	}
   165  }
   166  
   167  //head检索当前head哈希的副本以及
   168  //同龄人。
   169  func (p *peer) Head() (hash common.Hash, td *big.Int) {
   170  	p.lock.RLock()
   171  	defer p.lock.RUnlock()
   172  
   173  	copy(hash[:], p.head[:])
   174  	return hash, new(big.Int).Set(p.td)
   175  }
   176  
   177  //sethead更新头散列和对等端的总难度。
   178  func (p *peer) SetHead(hash common.Hash, td *big.Int) {
   179  	p.lock.Lock()
   180  	defer p.lock.Unlock()
   181  
   182  	copy(p.head[:], hash[:])
   183  	p.td.Set(td)
   184  }
   185  
   186  //markblock将一个块标记为对等方已知的块,确保该块
   187  //永远不要传播到这个特定的对等端。
   188  func (p *peer) MarkBlock(hash common.Hash) {
   189  //如果达到了内存允许值,请删除以前已知的块哈希
   190  	for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   191  		p.knownBlocks.Pop()
   192  	}
   193  	p.knownBlocks.Add(hash)
   194  }
   195  
   196  //marktransaction将事务标记为对等方已知的事务,确保
   197  //永远不会传播到这个特定的对等。
   198  func (p *peer) MarkTransaction(hash common.Hash) {
   199  //如果达到了内存允许值,请删除以前已知的事务哈希
   200  	for p.knownTxs.Cardinality() >= maxKnownTxs {
   201  		p.knownTxs.Pop()
   202  	}
   203  	p.knownTxs.Add(hash)
   204  }
   205  
   206  //sendTransactions将事务发送到对等端,并包括哈希
   207  //在其事务哈希集中,以供将来参考。
   208  func (p *peer) SendTransactions(txs types.Transactions) error {
   209  	for _, tx := range txs {
   210  		p.knownTxs.Add(tx.Hash())
   211  	}
   212  	return p2p.Send(p.rw, TxMsg, txs)
   213  }
   214  
   215  //AsyncSendTransactions队列将事务传播到远程的列表
   216  //同龄人。如果对等方的广播队列已满,则会静默地删除事件。
   217  func (p *peer) AsyncSendTransactions(txs []*types.Transaction) {
   218  	select {
   219  	case p.queuedTxs <- txs:
   220  		for _, tx := range txs {
   221  			p.knownTxs.Add(tx.Hash())
   222  		}
   223  	default:
   224  		p.Log().Debug("Dropping transaction propagation", "count", len(txs))
   225  	}
   226  }
   227  
   228  //sendNewBlockHashes宣布通过
   229  //哈希通知。
   230  func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error {
   231  	for _, hash := range hashes {
   232  		p.knownBlocks.Add(hash)
   233  	}
   234  	request := make(newBlockHashesData, len(hashes))
   235  	for i := 0; i < len(hashes); i++ {
   236  		request[i].Hash = hashes[i]
   237  		request[i].Number = numbers[i]
   238  	}
   239  	return p2p.Send(p.rw, NewBlockHashesMsg, request)
   240  }
   241  
   242  //AsyncSendNewBlockHash将用于传播到
   243  //远程对等体。如果对等方的广播队列已满,则事件将静默
   244  //下降。
   245  func (p *peer) AsyncSendNewBlockHash(block *types.Block) {
   246  	select {
   247  	case p.queuedAnns <- block:
   248  		p.knownBlocks.Add(block.Hash())
   249  	default:
   250  		p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash())
   251  	}
   252  }
   253  
   254  //sendNewBlock将整个块传播到远程对等机。
   255  func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error {
   256  	p.knownBlocks.Add(block.Hash())
   257  	return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td})
   258  }
   259  
   260  //AsyncSendNewBlock将整个块排队,以便传播到远程对等端。如果
   261  //对等机的广播队列已满,事件将被静默丢弃。
   262  func (p *peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
   263  	select {
   264  	case p.queuedProps <- &propEvent{block: block, td: td}:
   265  		p.knownBlocks.Add(block.Hash())
   266  	default:
   267  		p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash())
   268  	}
   269  }
   270  
   271  //sendblockheaders向远程对等端发送一批块头。
   272  func (p *peer) SendBlockHeaders(headers []*types.Header) error {
   273  	return p2p.Send(p.rw, BlockHeadersMsg, headers)
   274  }
   275  
   276  //sendblockbody向远程对等发送一批块内容。
   277  func (p *peer) SendBlockBodies(bodies []*blockBody) error {
   278  	return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies))
   279  }
   280  
   281  //sendblockbodiesrlp从发送一批块内容到远程对等机
   282  //已经用rlp编码的格式。
   283  func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error {
   284  	return p2p.Send(p.rw, BlockBodiesMsg, bodies)
   285  }
   286  
   287  //sendNoedatarlp发送一批任意内部数据,与
   288  //已请求哈希。
   289  func (p *peer) SendNodeData(data [][]byte) error {
   290  	return p2p.Send(p.rw, NodeDataMsg, data)
   291  }
   292  
   293  //sendReceiptsRLP发送一批交易凭证,与
   294  //从已经RLP编码的格式请求的。
   295  func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error {
   296  	return p2p.Send(p.rw, ReceiptsMsg, receipts)
   297  }
   298  
   299  //RequestOneHeader是一个包装器,它围绕头查询函数来获取
   300  //单头。它仅由取纸器使用。
   301  func (p *peer) RequestOneHeader(hash common.Hash) error {
   302  	p.Log().Debug("Fetching single header", "hash", hash)
   303  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false})
   304  }
   305  
   306  //RequestHeadersByHash获取与
   307  //基于源块哈希的指定头查询。
   308  func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error {
   309  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse)
   310  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   311  }
   312  
   313  //RequestHeadersByNumber获取与
   314  //指定的头查询,基于源块的编号。
   315  func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error {
   316  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse)
   317  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   318  }
   319  
   320  //请求主体获取一批与哈希对应的块的主体
   321  //明确规定。
   322  func (p *peer) RequestBodies(hashes []common.Hash) error {
   323  	p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
   324  	return p2p.Send(p.rw, GetBlockBodiesMsg, hashes)
   325  }
   326  
   327  //RequestNodeData从节点的已知状态获取一批任意数据
   328  //与指定哈希对应的数据。
   329  func (p *peer) RequestNodeData(hashes []common.Hash) error {
   330  	p.Log().Debug("Fetching batch of state data", "count", len(hashes))
   331  	return p2p.Send(p.rw, GetNodeDataMsg, hashes)
   332  }
   333  
   334  //RequestReceipts从远程节点获取一批事务收据。
   335  func (p *peer) RequestReceipts(hashes []common.Hash) error {
   336  	p.Log().Debug("Fetching batch of receipts", "count", len(hashes))
   337  	return p2p.Send(p.rw, GetReceiptsMsg, hashes)
   338  }
   339  
   340  //握手执行ETH协议握手,协商版本号,
   341  //网络ID,困难,头和创世块。
   342  func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash) error {
   343  //在新线程中发送自己的握手
   344  	errc := make(chan error, 2)
   345  var status statusData //从errc收到两个值后可以安全读取
   346  
   347  	go func() {
   348  		errc <- p2p.Send(p.rw, StatusMsg, &statusData{
   349  			ProtocolVersion: uint32(p.version),
   350  			NetworkId:       network,
   351  			TD:              td,
   352  			CurrentBlock:    head,
   353  			GenesisBlock:    genesis,
   354  		})
   355  	}()
   356  	go func() {
   357  		errc <- p.readStatus(network, &status, genesis)
   358  	}()
   359  	timeout := time.NewTimer(handshakeTimeout)
   360  	defer timeout.Stop()
   361  	for i := 0; i < 2; i++ {
   362  		select {
   363  		case err := <-errc:
   364  			if err != nil {
   365  				return err
   366  			}
   367  		case <-timeout.C:
   368  			return p2p.DiscReadTimeout
   369  		}
   370  	}
   371  	p.td, p.head = status.TD, status.CurrentBlock
   372  	return nil
   373  }
   374  
   375  func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash) (err error) {
   376  	msg, err := p.rw.ReadMsg()
   377  	if err != nil {
   378  		return err
   379  	}
   380  	if msg.Code != StatusMsg {
   381  		return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
   382  	}
   383  	if msg.Size > ProtocolMaxMsgSize {
   384  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   385  	}
   386  //解码握手并确保所有内容都匹配
   387  	if err := msg.Decode(&status); err != nil {
   388  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   389  	}
   390  	if status.GenesisBlock != genesis {
   391  		return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8])
   392  	}
   393  	if status.NetworkId != network {
   394  		return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network)
   395  	}
   396  	if int(status.ProtocolVersion) != p.version {
   397  		return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
   398  	}
   399  	return nil
   400  }
   401  
   402  //字符串实现fmt.stringer。
   403  func (p *peer) String() string {
   404  	return fmt.Sprintf("Peer %s [%s]", p.id,
   405  		fmt.Sprintf("eth/%2d", p.version),
   406  	)
   407  }
   408  
   409  //Peerset表示当前参与的活动对等机的集合
   410  //以太坊子协议。
   411  type peerSet struct {
   412  	peers  map[string]*peer
   413  	lock   sync.RWMutex
   414  	closed bool
   415  }
   416  
   417  //new peer set创建一个新的对等集来跟踪活动参与者。
   418  func newPeerSet() *peerSet {
   419  	return &peerSet{
   420  		peers: make(map[string]*peer),
   421  	}
   422  }
   423  
   424  //寄存器向工作集中注入一个新的对等点,或者返回一个错误,如果
   425  //对等机已经知道。如果注册了一个新的对等点,其广播循环也
   426  //起动。
   427  func (ps *peerSet) Register(p *peer) error {
   428  	ps.lock.Lock()
   429  	defer ps.lock.Unlock()
   430  
   431  	if ps.closed {
   432  		return errClosed
   433  	}
   434  	if _, ok := ps.peers[p.id]; ok {
   435  		return errAlreadyRegistered
   436  	}
   437  	ps.peers[p.id] = p
   438  	go p.broadcast()
   439  
   440  	return nil
   441  }
   442  
   443  //注销从活动集删除远程对等,进一步禁用
   444  //对该特定实体采取的行动。
   445  func (ps *peerSet) Unregister(id string) error {
   446  	ps.lock.Lock()
   447  	defer ps.lock.Unlock()
   448  
   449  	p, ok := ps.peers[id]
   450  	if !ok {
   451  		return errNotRegistered
   452  	}
   453  	delete(ps.peers, id)
   454  	p.close()
   455  
   456  	return nil
   457  }
   458  
   459  //对等端检索具有给定ID的注册对等端。
   460  func (ps *peerSet) Peer(id string) *peer {
   461  	ps.lock.RLock()
   462  	defer ps.lock.RUnlock()
   463  
   464  	return ps.peers[id]
   465  }
   466  
   467  //len返回集合中当前的对等数。
   468  func (ps *peerSet) Len() int {
   469  	ps.lock.RLock()
   470  	defer ps.lock.RUnlock()
   471  
   472  	return len(ps.peers)
   473  }
   474  
   475  //peerswithoutblock检索没有给定块的对等机列表
   476  //他们的一组已知散列。
   477  func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer {
   478  	ps.lock.RLock()
   479  	defer ps.lock.RUnlock()
   480  
   481  	list := make([]*peer, 0, len(ps.peers))
   482  	for _, p := range ps.peers {
   483  		if !p.knownBlocks.Contains(hash) {
   484  			list = append(list, p)
   485  		}
   486  	}
   487  	return list
   488  }
   489  
   490  //PeerSwithouttx检索没有给定事务的对等方列表
   491  //在他们的一组已知散列中。
   492  func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer {
   493  	ps.lock.RLock()
   494  	defer ps.lock.RUnlock()
   495  
   496  	list := make([]*peer, 0, len(ps.peers))
   497  	for _, p := range ps.peers {
   498  		if !p.knownTxs.Contains(hash) {
   499  			list = append(list, p)
   500  		}
   501  	}
   502  	return list
   503  }
   504  
   505  //BestPeer以当前最高的总难度检索已知的对等。
   506  func (ps *peerSet) BestPeer() *peer {
   507  	ps.lock.RLock()
   508  	defer ps.lock.RUnlock()
   509  
   510  	var (
   511  		bestPeer *peer
   512  		bestTd   *big.Int
   513  	)
   514  	for _, p := range ps.peers {
   515  		if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 {
   516  			bestPeer, bestTd = p, td
   517  		}
   518  	}
   519  	return bestPeer
   520  }
   521  
   522  //关闭将断开所有对等机的连接。
   523  //关闭后不能注册新的对等方。
   524  func (ps *peerSet) Close() {
   525  	ps.lock.Lock()
   526  	defer ps.lock.Unlock()
   527  
   528  	for _, p := range ps.peers {
   529  		p.Disconnect(p2p.DiscQuitting)
   530  	}
   531  	ps.closed = true
   532  }