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