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