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