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