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