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