github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/eth/peer.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package eth 18 19 import ( 20 "errors" 21 "fmt" 22 "math/big" 23 "sync" 24 "time" 25 26 mapset "github.com/deckarep/golang-set" 27 "github.com/zhiqiangxu/go-ethereum/common" 28 "github.com/zhiqiangxu/go-ethereum/core/forkid" 29 "github.com/zhiqiangxu/go-ethereum/core/types" 30 "github.com/zhiqiangxu/go-ethereum/p2p" 31 "github.com/zhiqiangxu/go-ethereum/rlp" 32 ) 33 34 var ( 35 errClosed = errors.New("peer set is closed") 36 errAlreadyRegistered = errors.New("peer is already registered") 37 errNotRegistered = errors.New("peer is not registered") 38 ) 39 40 const ( 41 maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) 42 maxKnownBlocks = 1024 // Maximum block hashes to keep in the known list (prevent DOS) 43 44 // maxQueuedTxs is the maximum number of transactions to queue up before dropping 45 // older broadcasts. 46 maxQueuedTxs = 4096 47 48 // maxQueuedTxAnns is the maximum number of transaction announcements to queue up 49 // before dropping older announcements. 50 maxQueuedTxAnns = 4096 51 52 // maxQueuedBlocks is the maximum number of block propagations to queue up before 53 // dropping broadcasts. There's not much point in queueing stale blocks, so a few 54 // that might cover uncles should be enough. 55 maxQueuedBlocks = 4 56 57 // maxQueuedBlockAnns is the maximum number of block announcements to queue up before 58 // dropping broadcasts. Similarly to block propagations, there's no point to queue 59 // above some healthy uncle limit, so use that. 60 maxQueuedBlockAnns = 4 61 62 handshakeTimeout = 5 * time.Second 63 ) 64 65 // max is a helper function which returns the larger of the two given integers. 66 func max(a, b int) int { 67 if a > b { 68 return a 69 } 70 return b 71 } 72 73 // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known 74 // about a connected peer. 75 type PeerInfo struct { 76 Version int `json:"version"` // Ethereum protocol version negotiated 77 Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain 78 Head string `json:"head"` // SHA3 hash of the peer's best owned block 79 } 80 81 // propEvent is a block propagation, waiting for its turn in the broadcast queue. 82 type propEvent struct { 83 block *types.Block 84 td *big.Int 85 } 86 87 type peer struct { 88 id string 89 90 *p2p.Peer 91 rw p2p.MsgReadWriter 92 93 version int // Protocol version negotiated 94 syncDrop *time.Timer // Timed connection dropper if sync progress isn't validated in time 95 96 head common.Hash 97 td *big.Int 98 lock sync.RWMutex 99 100 knownBlocks mapset.Set // Set of block hashes known to be known by this peer 101 queuedBlocks chan *propEvent // Queue of blocks to broadcast to the peer 102 queuedBlockAnns chan *types.Block // Queue of blocks to announce to the peer 103 104 knownTxs mapset.Set // Set of transaction hashes known to be known by this peer 105 txBroadcast chan []common.Hash // Channel used to queue transaction propagation requests 106 txAnnounce chan []common.Hash // Channel used to queue transaction announcement requests 107 getPooledTx func(common.Hash) *types.Transaction // Callback used to retrieve transaction from txpool 108 109 term chan struct{} // Termination channel to stop the broadcaster 110 } 111 112 func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter, getPooledTx func(hash common.Hash) *types.Transaction) *peer { 113 return &peer{ 114 Peer: p, 115 rw: rw, 116 version: version, 117 id: fmt.Sprintf("%x", p.ID().Bytes()[:8]), 118 knownTxs: mapset.NewSet(), 119 knownBlocks: mapset.NewSet(), 120 queuedBlocks: make(chan *propEvent, maxQueuedBlocks), 121 queuedBlockAnns: make(chan *types.Block, maxQueuedBlockAnns), 122 txBroadcast: make(chan []common.Hash), 123 txAnnounce: make(chan []common.Hash), 124 getPooledTx: getPooledTx, 125 term: make(chan struct{}), 126 } 127 } 128 129 // broadcastBlocks is a write loop that multiplexes blocks and block accouncements 130 // to the remote peer. The goal is to have an async writer that does not lock up 131 // node internals and at the same time rate limits queued data. 132 func (p *peer) broadcastBlocks() { 133 for { 134 select { 135 case prop := <-p.queuedBlocks: 136 if err := p.SendNewBlock(prop.block, prop.td); err != nil { 137 return 138 } 139 p.Log().Trace("Propagated block", "number", prop.block.Number(), "hash", prop.block.Hash(), "td", prop.td) 140 141 case block := <-p.queuedBlockAnns: 142 if err := p.SendNewBlockHashes([]common.Hash{block.Hash()}, []uint64{block.NumberU64()}); err != nil { 143 return 144 } 145 p.Log().Trace("Announced block", "number", block.Number(), "hash", block.Hash()) 146 147 case <-p.term: 148 return 149 } 150 } 151 } 152 153 // broadcastTransactions is a write loop that schedules transaction broadcasts 154 // to the remote peer. The goal is to have an async writer that does not lock up 155 // node internals and at the same time rate limits queued data. 156 func (p *peer) broadcastTransactions() { 157 var ( 158 queue []common.Hash // Queue of hashes to broadcast as full transactions 159 done chan struct{} // Non-nil if background broadcaster is running 160 fail = make(chan error, 1) // Channel used to receive network error 161 ) 162 for { 163 // If there's no in-flight broadcast running, check if a new one is needed 164 if done == nil && len(queue) > 0 { 165 // Pile transaction until we reach our allowed network limit 166 var ( 167 hashes []common.Hash 168 txs []*types.Transaction 169 size common.StorageSize 170 ) 171 for i := 0; i < len(queue) && size < txsyncPackSize; i++ { 172 if tx := p.getPooledTx(queue[i]); tx != nil { 173 txs = append(txs, tx) 174 size += tx.Size() 175 } 176 hashes = append(hashes, queue[i]) 177 } 178 queue = queue[:copy(queue, queue[len(hashes):])] 179 180 // If there's anything available to transfer, fire up an async writer 181 if len(txs) > 0 { 182 done = make(chan struct{}) 183 go func() { 184 if err := p.sendTransactions(txs); err != nil { 185 fail <- err 186 return 187 } 188 close(done) 189 p.Log().Trace("Sent transactions", "count", len(txs)) 190 }() 191 } 192 } 193 // Transfer goroutine may or may not have been started, listen for events 194 select { 195 case hashes := <-p.txBroadcast: 196 // New batch of transactions to be broadcast, queue them (with cap) 197 queue = append(queue, hashes...) 198 if len(queue) > maxQueuedTxs { 199 // Fancy copy and resize to ensure buffer doesn't grow indefinitely 200 queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxs:])] 201 } 202 203 case <-done: 204 done = nil 205 206 case <-fail: 207 return 208 209 case <-p.term: 210 return 211 } 212 } 213 } 214 215 // announceTransactions is a write loop that schedules transaction broadcasts 216 // to the remote peer. The goal is to have an async writer that does not lock up 217 // node internals and at the same time rate limits queued data. 218 func (p *peer) announceTransactions() { 219 var ( 220 queue []common.Hash // Queue of hashes to announce as transaction stubs 221 done chan struct{} // Non-nil if background announcer is running 222 fail = make(chan error, 1) // Channel used to receive network error 223 ) 224 for { 225 // If there's no in-flight announce running, check if a new one is needed 226 if done == nil && len(queue) > 0 { 227 // Pile transaction hashes until we reach our allowed network limit 228 var ( 229 hashes []common.Hash 230 pending []common.Hash 231 size common.StorageSize 232 ) 233 for i := 0; i < len(queue) && size < txsyncPackSize; i++ { 234 if p.getPooledTx(queue[i]) != nil { 235 pending = append(pending, queue[i]) 236 size += common.HashLength 237 } 238 hashes = append(hashes, queue[i]) 239 } 240 queue = queue[:copy(queue, queue[len(hashes):])] 241 242 // If there's anything available to transfer, fire up an async writer 243 if len(pending) > 0 { 244 done = make(chan struct{}) 245 go func() { 246 if err := p.sendPooledTransactionHashes(pending); err != nil { 247 fail <- err 248 return 249 } 250 close(done) 251 p.Log().Trace("Sent transaction announcements", "count", len(pending)) 252 }() 253 } 254 } 255 // Transfer goroutine may or may not have been started, listen for events 256 select { 257 case hashes := <-p.txAnnounce: 258 // New batch of transactions to be broadcast, queue them (with cap) 259 queue = append(queue, hashes...) 260 if len(queue) > maxQueuedTxAnns { 261 // Fancy copy and resize to ensure buffer doesn't grow indefinitely 262 queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxs:])] 263 } 264 265 case <-done: 266 done = nil 267 268 case <-fail: 269 return 270 271 case <-p.term: 272 return 273 } 274 } 275 } 276 277 // close signals the broadcast goroutine to terminate. 278 func (p *peer) close() { 279 close(p.term) 280 } 281 282 // Info gathers and returns a collection of metadata known about a peer. 283 func (p *peer) Info() *PeerInfo { 284 hash, td := p.Head() 285 286 return &PeerInfo{ 287 Version: p.version, 288 Difficulty: td, 289 Head: hash.Hex(), 290 } 291 } 292 293 // Head retrieves a copy of the current head hash and total difficulty of the 294 // peer. 295 func (p *peer) Head() (hash common.Hash, td *big.Int) { 296 p.lock.RLock() 297 defer p.lock.RUnlock() 298 299 copy(hash[:], p.head[:]) 300 return hash, new(big.Int).Set(p.td) 301 } 302 303 // SetHead updates the head hash and total difficulty of the peer. 304 func (p *peer) SetHead(hash common.Hash, td *big.Int) { 305 p.lock.Lock() 306 defer p.lock.Unlock() 307 308 copy(p.head[:], hash[:]) 309 p.td.Set(td) 310 } 311 312 // MarkBlock marks a block as known for the peer, ensuring that the block will 313 // never be propagated to this particular peer. 314 func (p *peer) MarkBlock(hash common.Hash) { 315 // If we reached the memory allowance, drop a previously known block hash 316 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 317 p.knownBlocks.Pop() 318 } 319 p.knownBlocks.Add(hash) 320 } 321 322 // MarkTransaction marks a transaction as known for the peer, ensuring that it 323 // will never be propagated to this particular peer. 324 func (p *peer) MarkTransaction(hash common.Hash) { 325 // If we reached the memory allowance, drop a previously known transaction hash 326 for p.knownTxs.Cardinality() >= maxKnownTxs { 327 p.knownTxs.Pop() 328 } 329 p.knownTxs.Add(hash) 330 } 331 332 // SendTransactions64 sends transactions to the peer and includes the hashes 333 // in its transaction hash set for future reference. 334 // 335 // This method is legacy support for initial transaction exchange in eth/64 and 336 // prior. For eth/65 and higher use SendPooledTransactionHashes. 337 func (p *peer) SendTransactions64(txs types.Transactions) error { 338 return p.sendTransactions(txs) 339 } 340 341 // sendTransactions sends transactions to the peer and includes the hashes 342 // in its transaction hash set for future reference. 343 // 344 // This method is a helper used by the async transaction sender. Don't call it 345 // directly as the queueing (memory) and transmission (bandwidth) costs should 346 // not be managed directly. 347 func (p *peer) sendTransactions(txs types.Transactions) error { 348 // Mark all the transactions as known, but ensure we don't overflow our limits 349 for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(txs)) { 350 p.knownTxs.Pop() 351 } 352 for _, tx := range txs { 353 p.knownTxs.Add(tx.Hash()) 354 } 355 return p2p.Send(p.rw, TransactionMsg, txs) 356 } 357 358 // AsyncSendTransactions queues a list of transactions (by hash) to eventually 359 // propagate to a remote peer. The number of pending sends are capped (new ones 360 // will force old sends to be dropped) 361 func (p *peer) AsyncSendTransactions(hashes []common.Hash) { 362 select { 363 case p.txBroadcast <- hashes: 364 // Mark all the transactions as known, but ensure we don't overflow our limits 365 for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { 366 p.knownTxs.Pop() 367 } 368 for _, hash := range hashes { 369 p.knownTxs.Add(hash) 370 } 371 case <-p.term: 372 p.Log().Debug("Dropping transaction propagation", "count", len(hashes)) 373 } 374 } 375 376 // sendPooledTransactionHashes sends transaction hashes to the peer and includes 377 // them in its transaction hash set for future reference. 378 // 379 // This method is a helper used by the async transaction announcer. Don't call it 380 // directly as the queueing (memory) and transmission (bandwidth) costs should 381 // not be managed directly. 382 func (p *peer) sendPooledTransactionHashes(hashes []common.Hash) error { 383 // Mark all the transactions as known, but ensure we don't overflow our limits 384 for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { 385 p.knownTxs.Pop() 386 } 387 for _, hash := range hashes { 388 p.knownTxs.Add(hash) 389 } 390 return p2p.Send(p.rw, NewPooledTransactionHashesMsg, hashes) 391 } 392 393 // AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually 394 // announce to a remote peer. The number of pending sends are capped (new ones 395 // will force old sends to be dropped) 396 func (p *peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) { 397 select { 398 case p.txAnnounce <- hashes: 399 // Mark all the transactions as known, but ensure we don't overflow our limits 400 for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { 401 p.knownTxs.Pop() 402 } 403 for _, hash := range hashes { 404 p.knownTxs.Add(hash) 405 } 406 case <-p.term: 407 p.Log().Debug("Dropping transaction announcement", "count", len(hashes)) 408 } 409 } 410 411 // SendPooledTransactionsRLP sends requested transactions to the peer and adds the 412 // hashes in its transaction hash set for future reference. 413 // 414 // Note, the method assumes the hashes are correct and correspond to the list of 415 // transactions being sent. 416 func (p *peer) SendPooledTransactionsRLP(hashes []common.Hash, txs []rlp.RawValue) error { 417 // Mark all the transactions as known, but ensure we don't overflow our limits 418 for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { 419 p.knownTxs.Pop() 420 } 421 for _, hash := range hashes { 422 p.knownTxs.Add(hash) 423 } 424 return p2p.Send(p.rw, PooledTransactionsMsg, txs) 425 } 426 427 // SendNewBlockHashes announces the availability of a number of blocks through 428 // a hash notification. 429 func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { 430 // Mark all the block hashes as known, but ensure we don't overflow our limits 431 for p.knownBlocks.Cardinality() > max(0, maxKnownBlocks-len(hashes)) { 432 p.knownBlocks.Pop() 433 } 434 for _, hash := range hashes { 435 p.knownBlocks.Add(hash) 436 } 437 request := make(newBlockHashesData, len(hashes)) 438 for i := 0; i < len(hashes); i++ { 439 request[i].Hash = hashes[i] 440 request[i].Number = numbers[i] 441 } 442 return p2p.Send(p.rw, NewBlockHashesMsg, request) 443 } 444 445 // AsyncSendNewBlockHash queues the availability of a block for propagation to a 446 // remote peer. If the peer's broadcast queue is full, the event is silently 447 // dropped. 448 func (p *peer) AsyncSendNewBlockHash(block *types.Block) { 449 select { 450 case p.queuedBlockAnns <- block: 451 // Mark all the block hash as known, but ensure we don't overflow our limits 452 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 453 p.knownBlocks.Pop() 454 } 455 p.knownBlocks.Add(block.Hash()) 456 default: 457 p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) 458 } 459 } 460 461 // SendNewBlock propagates an entire block to a remote peer. 462 func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { 463 // Mark all the block hash as known, but ensure we don't overflow our limits 464 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 465 p.knownBlocks.Pop() 466 } 467 p.knownBlocks.Add(block.Hash()) 468 return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) 469 } 470 471 // AsyncSendNewBlock queues an entire block for propagation to a remote peer. If 472 // the peer's broadcast queue is full, the event is silently dropped. 473 func (p *peer) AsyncSendNewBlock(block *types.Block, td *big.Int) { 474 select { 475 case p.queuedBlocks <- &propEvent{block: block, td: td}: 476 // Mark all the block hash as known, but ensure we don't overflow our limits 477 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 478 p.knownBlocks.Pop() 479 } 480 p.knownBlocks.Add(block.Hash()) 481 default: 482 p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) 483 } 484 } 485 486 // SendBlockHeaders sends a batch of block headers to the remote peer. 487 func (p *peer) SendBlockHeaders(headers []*types.Header) error { 488 return p2p.Send(p.rw, BlockHeadersMsg, headers) 489 } 490 491 // SendBlockBodies sends a batch of block contents to the remote peer. 492 func (p *peer) SendBlockBodies(bodies []*blockBody) error { 493 return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) 494 } 495 496 // SendBlockBodiesRLP sends a batch of block contents to the remote peer from 497 // an already RLP encoded format. 498 func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error { 499 return p2p.Send(p.rw, BlockBodiesMsg, bodies) 500 } 501 502 // SendNodeDataRLP sends a batch of arbitrary internal data, corresponding to the 503 // hashes requested. 504 func (p *peer) SendNodeData(data [][]byte) error { 505 return p2p.Send(p.rw, NodeDataMsg, data) 506 } 507 508 // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the 509 // ones requested from an already RLP encoded format. 510 func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error { 511 return p2p.Send(p.rw, ReceiptsMsg, receipts) 512 } 513 514 // RequestOneHeader is a wrapper around the header query functions to fetch a 515 // single header. It is used solely by the fetcher. 516 func (p *peer) RequestOneHeader(hash common.Hash) error { 517 p.Log().Debug("Fetching single header", "hash", hash) 518 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) 519 } 520 521 // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the 522 // specified header query, based on the hash of an origin block. 523 func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 524 p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) 525 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 526 } 527 528 // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the 529 // specified header query, based on the number of an origin block. 530 func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 531 p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) 532 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 533 } 534 535 // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes 536 // specified. 537 func (p *peer) RequestBodies(hashes []common.Hash) error { 538 p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) 539 return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) 540 } 541 542 // RequestNodeData fetches a batch of arbitrary data from a node's known state 543 // data, corresponding to the specified hashes. 544 func (p *peer) RequestNodeData(hashes []common.Hash) error { 545 p.Log().Debug("Fetching batch of state data", "count", len(hashes)) 546 return p2p.Send(p.rw, GetNodeDataMsg, hashes) 547 } 548 549 // RequestReceipts fetches a batch of transaction receipts from a remote node. 550 func (p *peer) RequestReceipts(hashes []common.Hash) error { 551 p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) 552 return p2p.Send(p.rw, GetReceiptsMsg, hashes) 553 } 554 555 // RequestTxs fetches a batch of transactions from a remote node. 556 func (p *peer) RequestTxs(hashes []common.Hash) error { 557 p.Log().Debug("Fetching batch of transactions", "count", len(hashes)) 558 return p2p.Send(p.rw, GetPooledTransactionsMsg, hashes) 559 } 560 561 // Handshake executes the eth protocol handshake, negotiating version number, 562 // network IDs, difficulties, head and genesis blocks. 563 func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { 564 // Send out own handshake in a new thread 565 errc := make(chan error, 2) 566 567 var ( 568 status63 statusData63 // safe to read after two values have been received from errc 569 status statusData // safe to read after two values have been received from errc 570 ) 571 go func() { 572 switch { 573 case p.version == eth63: 574 errc <- p2p.Send(p.rw, StatusMsg, &statusData63{ 575 ProtocolVersion: uint32(p.version), 576 NetworkId: network, 577 TD: td, 578 CurrentBlock: head, 579 GenesisBlock: genesis, 580 }) 581 case p.version >= eth64: 582 errc <- p2p.Send(p.rw, StatusMsg, &statusData{ 583 ProtocolVersion: uint32(p.version), 584 NetworkID: network, 585 TD: td, 586 Head: head, 587 Genesis: genesis, 588 ForkID: forkID, 589 }) 590 default: 591 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 592 } 593 }() 594 go func() { 595 switch { 596 case p.version == eth63: 597 errc <- p.readStatusLegacy(network, &status63, genesis) 598 case p.version >= eth64: 599 errc <- p.readStatus(network, &status, genesis, forkFilter) 600 default: 601 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 602 } 603 }() 604 timeout := time.NewTimer(handshakeTimeout) 605 defer timeout.Stop() 606 for i := 0; i < 2; i++ { 607 select { 608 case err := <-errc: 609 if err != nil { 610 return err 611 } 612 case <-timeout.C: 613 return p2p.DiscReadTimeout 614 } 615 } 616 switch { 617 case p.version == eth63: 618 p.td, p.head = status63.TD, status63.CurrentBlock 619 case p.version >= eth64: 620 p.td, p.head = status.TD, status.Head 621 default: 622 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 623 } 624 return nil 625 } 626 627 func (p *peer) readStatusLegacy(network uint64, status *statusData63, genesis common.Hash) error { 628 msg, err := p.rw.ReadMsg() 629 if err != nil { 630 return err 631 } 632 if msg.Code != StatusMsg { 633 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 634 } 635 if msg.Size > protocolMaxMsgSize { 636 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) 637 } 638 // Decode the handshake and make sure everything matches 639 if err := msg.Decode(&status); err != nil { 640 return errResp(ErrDecode, "msg %v: %v", msg, err) 641 } 642 if status.GenesisBlock != genesis { 643 return errResp(ErrGenesisMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) 644 } 645 if status.NetworkId != network { 646 return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkId, network) 647 } 648 if int(status.ProtocolVersion) != p.version { 649 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 650 } 651 return nil 652 } 653 654 func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash, forkFilter forkid.Filter) error { 655 msg, err := p.rw.ReadMsg() 656 if err != nil { 657 return err 658 } 659 if msg.Code != StatusMsg { 660 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 661 } 662 if msg.Size > protocolMaxMsgSize { 663 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) 664 } 665 // Decode the handshake and make sure everything matches 666 if err := msg.Decode(&status); err != nil { 667 return errResp(ErrDecode, "msg %v: %v", msg, err) 668 } 669 if status.NetworkID != network { 670 return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkID, network) 671 } 672 if int(status.ProtocolVersion) != p.version { 673 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 674 } 675 if status.Genesis != genesis { 676 return errResp(ErrGenesisMismatch, "%x (!= %x)", status.Genesis, genesis) 677 } 678 if err := forkFilter(status.ForkID); err != nil { 679 return errResp(ErrForkIDRejected, "%v", err) 680 } 681 return nil 682 } 683 684 // String implements fmt.Stringer. 685 func (p *peer) String() string { 686 return fmt.Sprintf("Peer %s [%s]", p.id, 687 fmt.Sprintf("eth/%2d", p.version), 688 ) 689 } 690 691 // peerSet represents the collection of active peers currently participating in 692 // the Ethereum sub-protocol. 693 type peerSet struct { 694 peers map[string]*peer 695 lock sync.RWMutex 696 closed bool 697 } 698 699 // newPeerSet creates a new peer set to track the active participants. 700 func newPeerSet() *peerSet { 701 return &peerSet{ 702 peers: make(map[string]*peer), 703 } 704 } 705 706 // Register injects a new peer into the working set, or returns an error if the 707 // peer is already known. If a new peer it registered, its broadcast loop is also 708 // started. 709 func (ps *peerSet) Register(p *peer) error { 710 ps.lock.Lock() 711 defer ps.lock.Unlock() 712 713 if ps.closed { 714 return errClosed 715 } 716 if _, ok := ps.peers[p.id]; ok { 717 return errAlreadyRegistered 718 } 719 ps.peers[p.id] = p 720 721 go p.broadcastBlocks() 722 go p.broadcastTransactions() 723 if p.version >= eth65 { 724 go p.announceTransactions() 725 } 726 return nil 727 } 728 729 // Unregister removes a remote peer from the active set, disabling any further 730 // actions to/from that particular entity. 731 func (ps *peerSet) Unregister(id string) error { 732 ps.lock.Lock() 733 defer ps.lock.Unlock() 734 735 p, ok := ps.peers[id] 736 if !ok { 737 return errNotRegistered 738 } 739 delete(ps.peers, id) 740 p.close() 741 742 return nil 743 } 744 745 // Peer retrieves the registered peer with the given id. 746 func (ps *peerSet) Peer(id string) *peer { 747 ps.lock.RLock() 748 defer ps.lock.RUnlock() 749 750 return ps.peers[id] 751 } 752 753 // Len returns if the current number of peers in the set. 754 func (ps *peerSet) Len() int { 755 ps.lock.RLock() 756 defer ps.lock.RUnlock() 757 758 return len(ps.peers) 759 } 760 761 // PeersWithoutBlock retrieves a list of peers that do not have a given block in 762 // their set of known hashes. 763 func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer { 764 ps.lock.RLock() 765 defer ps.lock.RUnlock() 766 767 list := make([]*peer, 0, len(ps.peers)) 768 for _, p := range ps.peers { 769 if !p.knownBlocks.Contains(hash) { 770 list = append(list, p) 771 } 772 } 773 return list 774 } 775 776 // PeersWithoutTx retrieves a list of peers that do not have a given transaction 777 // in their set of known hashes. 778 func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer { 779 ps.lock.RLock() 780 defer ps.lock.RUnlock() 781 782 list := make([]*peer, 0, len(ps.peers)) 783 for _, p := range ps.peers { 784 if !p.knownTxs.Contains(hash) { 785 list = append(list, p) 786 } 787 } 788 return list 789 } 790 791 // BestPeer retrieves the known peer with the currently highest total difficulty. 792 func (ps *peerSet) BestPeer() *peer { 793 ps.lock.RLock() 794 defer ps.lock.RUnlock() 795 796 var ( 797 bestPeer *peer 798 bestTd *big.Int 799 ) 800 for _, p := range ps.peers { 801 if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 { 802 bestPeer, bestTd = p, td 803 } 804 } 805 return bestPeer 806 } 807 808 // Close disconnects all peers. 809 // No new peers can be registered after Close has returned. 810 func (ps *peerSet) Close() { 811 ps.lock.Lock() 812 defer ps.lock.Unlock() 813 814 for _, p := range ps.peers { 815 p.Disconnect(p2p.DiscQuitting) 816 } 817 ps.closed = true 818 }