github.com/coltonfike/e2c@v21.1.0+incompatible/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 "github.com/deckarep/golang-set" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus" 29 "github.com/ethereum/go-ethereum/core/forkid" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/p2p" 32 "github.com/ethereum/go-ethereum/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 transaction lists to queue up before 46 // dropping broadcasts. This is a sensitive number as a transaction list might 47 // contain a single transaction, or thousands. 48 maxQueuedTxs = 128 49 50 // maxQueuedProps is the maximum number of block propagations to queue up before 51 // dropping broadcasts. There's not much point in queueing stale blocks, so a few 52 // that might cover uncles should be enough. 53 maxQueuedProps = 4 54 55 // maxQueuedAnns is the maximum number of block announcements to queue up before 56 // dropping broadcasts. Similarly to block propagations, there's no point to queue 57 // above some healthy uncle limit, so use that. 58 maxQueuedAnns = 4 59 60 handshakeTimeout = 5 * time.Second 61 ) 62 63 // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known 64 // about a connected peer. 65 type PeerInfo struct { 66 Version int `json:"version"` // Ethereum protocol version negotiated 67 Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain 68 Head string `json:"head"` // SHA3 hash of the peer's best owned block 69 } 70 71 // propEvent is a block propagation, waiting for its turn in the broadcast queue. 72 type propEvent struct { 73 block *types.Block 74 td *big.Int 75 } 76 77 type peer struct { 78 id string 79 80 *p2p.Peer 81 rw p2p.MsgReadWriter 82 83 version int // Protocol version negotiated 84 syncDrop *time.Timer // Timed connection dropper if sync progress isn't validated in time 85 86 head common.Hash 87 td *big.Int 88 lock sync.RWMutex 89 90 knownTxs mapset.Set // Set of transaction hashes known to be known by this peer 91 knownBlocks mapset.Set // Set of block hashes known to be known by this peer 92 queuedTxs chan []*types.Transaction // Queue of transactions to broadcast to the peer 93 queuedProps chan *propEvent // Queue of blocks to broadcast to the peer 94 queuedAnns chan *types.Block // Queue of blocks to announce to the peer 95 term chan struct{} // Termination channel to stop the broadcaster 96 } 97 98 func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 99 return &peer{ 100 Peer: p, 101 rw: rw, 102 version: version, 103 id: fmt.Sprintf("%x", p.ID().Bytes()[:8]), 104 knownTxs: mapset.NewSet(), 105 knownBlocks: mapset.NewSet(), 106 queuedTxs: make(chan []*types.Transaction, maxQueuedTxs), 107 queuedProps: make(chan *propEvent, maxQueuedProps), 108 queuedAnns: make(chan *types.Block, maxQueuedAnns), 109 term: make(chan struct{}), 110 } 111 } 112 113 // broadcast is a write loop that multiplexes block propagations, announcements 114 // and transaction broadcasts into the remote peer. The goal is to have an async 115 // writer that does not lock up node internals. 116 func (p *peer) broadcast() { 117 for { 118 select { 119 case txs := <-p.queuedTxs: 120 if err := p.SendTransactions(txs); err != nil { 121 return 122 } 123 p.Log().Trace("Broadcast transactions", "count", len(txs)) 124 125 case prop := <-p.queuedProps: 126 if err := p.SendNewBlock(prop.block, prop.td); err != nil { 127 return 128 } 129 p.Log().Trace("Propagated block", "number", prop.block.Number(), "hash", prop.block.Hash(), "td", prop.td) 130 131 case block := <-p.queuedAnns: 132 if err := p.SendNewBlockHashes([]common.Hash{block.Hash()}, []uint64{block.NumberU64()}); err != nil { 133 return 134 } 135 p.Log().Trace("Announced block", "number", block.Number(), "hash", block.Hash()) 136 137 case <-p.term: 138 return 139 } 140 } 141 } 142 143 // close signals the broadcast goroutine to terminate. 144 func (p *peer) close() { 145 close(p.term) 146 } 147 148 // Info gathers and returns a collection of metadata known about a peer. 149 func (p *peer) Info() *PeerInfo { 150 hash, td := p.Head() 151 152 return &PeerInfo{ 153 Version: p.version, 154 Difficulty: td, 155 Head: hash.Hex(), 156 } 157 } 158 159 // Head retrieves a copy of the current head hash and total difficulty of the 160 // peer. 161 func (p *peer) Head() (hash common.Hash, td *big.Int) { 162 p.lock.RLock() 163 defer p.lock.RUnlock() 164 165 copy(hash[:], p.head[:]) 166 return hash, new(big.Int).Set(p.td) 167 } 168 169 // SetHead updates the head hash and total difficulty of the peer. 170 func (p *peer) SetHead(hash common.Hash, td *big.Int) { 171 p.lock.Lock() 172 defer p.lock.Unlock() 173 174 copy(p.head[:], hash[:]) 175 p.td.Set(td) 176 } 177 178 // MarkBlock marks a block as known for the peer, ensuring that the block will 179 // never be propagated to this particular peer. 180 func (p *peer) MarkBlock(hash common.Hash) { 181 // If we reached the memory allowance, drop a previously known block hash 182 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 183 p.knownBlocks.Pop() 184 } 185 p.knownBlocks.Add(hash) 186 } 187 188 // MarkTransaction marks a transaction as known for the peer, ensuring that it 189 // will never be propagated to this particular peer. 190 func (p *peer) MarkTransaction(hash common.Hash) { 191 // If we reached the memory allowance, drop a previously known transaction hash 192 for p.knownTxs.Cardinality() >= maxKnownTxs { 193 p.knownTxs.Pop() 194 } 195 p.knownTxs.Add(hash) 196 } 197 198 // Send writes an RLP-encoded message with the given code. 199 // data should encode as an RLP list. 200 func (p *peer) Send(msgcode uint64, data interface{}) error { 201 return p2p.Send(p.rw, msgcode, data) 202 } 203 204 // SendTransactions sends transactions to the peer and includes the hashes 205 // in its transaction hash set for future reference. 206 func (p *peer) SendTransactions(txs types.Transactions) error { 207 // Mark all the transactions as known, but ensure we don't overflow our limits 208 for _, tx := range txs { 209 p.knownTxs.Add(tx.Hash()) 210 } 211 for p.knownTxs.Cardinality() >= maxKnownTxs { 212 p.knownTxs.Pop() 213 } 214 return p2p.Send(p.rw, TxMsg, txs) 215 } 216 217 // AsyncSendTransactions queues list of transactions propagation to a remote 218 // peer. If the peer's broadcast queue is full, the event is silently dropped. 219 func (p *peer) AsyncSendTransactions(txs []*types.Transaction) { 220 select { 221 case p.queuedTxs <- txs: 222 // Mark all the transactions as known, but ensure we don't overflow our limits 223 for _, tx := range txs { 224 p.knownTxs.Add(tx.Hash()) 225 } 226 for p.knownTxs.Cardinality() >= maxKnownTxs { 227 p.knownTxs.Pop() 228 } 229 default: 230 p.Log().Debug("Dropping transaction propagation", "count", len(txs)) 231 } 232 } 233 234 // SendNewBlockHashes announces the availability of a number of blocks through 235 // a hash notification. 236 func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { 237 // Mark all the block hashes as known, but ensure we don't overflow our limits 238 for _, hash := range hashes { 239 p.knownBlocks.Add(hash) 240 } 241 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 242 p.knownBlocks.Pop() 243 } 244 request := make(newBlockHashesData, len(hashes)) 245 for i := 0; i < len(hashes); i++ { 246 request[i].Hash = hashes[i] 247 request[i].Number = numbers[i] 248 } 249 return p2p.Send(p.rw, NewBlockHashesMsg, request) 250 } 251 252 // AsyncSendNewBlockHash queues the availability of a block for propagation to a 253 // remote peer. If the peer's broadcast queue is full, the event is silently 254 // dropped. 255 func (p *peer) AsyncSendNewBlockHash(block *types.Block) { 256 select { 257 case p.queuedAnns <- block: 258 // Mark all the block hash as known, but ensure we don't overflow our limits 259 p.knownBlocks.Add(block.Hash()) 260 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 261 p.knownBlocks.Pop() 262 } 263 default: 264 p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) 265 } 266 } 267 268 // SendNewBlock propagates an entire block to a remote peer. 269 func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { 270 // Mark all the block hash as known, but ensure we don't overflow our limits 271 p.knownBlocks.Add(block.Hash()) 272 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 273 p.knownBlocks.Pop() 274 } 275 return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) 276 } 277 278 // AsyncSendNewBlock queues an entire block for propagation to a remote peer. If 279 // the peer's broadcast queue is full, the event is silently dropped. 280 func (p *peer) AsyncSendNewBlock(block *types.Block, td *big.Int) { 281 select { 282 case p.queuedProps <- &propEvent{block: block, td: td}: 283 // Mark all the block hash as known, but ensure we don't overflow our limits 284 p.knownBlocks.Add(block.Hash()) 285 for p.knownBlocks.Cardinality() >= maxKnownBlocks { 286 p.knownBlocks.Pop() 287 } 288 default: 289 p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) 290 } 291 } 292 293 // SendBlockHeaders sends a batch of block headers to the remote peer. 294 func (p *peer) SendBlockHeaders(headers []*types.Header) error { 295 return p2p.Send(p.rw, BlockHeadersMsg, headers) 296 } 297 298 // SendBlockBodies sends a batch of block contents to the remote peer. 299 func (p *peer) SendBlockBodies(bodies []*blockBody) error { 300 return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) 301 } 302 303 // SendBlockBodiesRLP sends a batch of block contents to the remote peer from 304 // an already RLP encoded format. 305 func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error { 306 return p2p.Send(p.rw, BlockBodiesMsg, bodies) 307 } 308 309 // SendNodeDataRLP sends a batch of arbitrary internal data, corresponding to the 310 // hashes requested. 311 func (p *peer) SendNodeData(data [][]byte) error { 312 return p2p.Send(p.rw, NodeDataMsg, data) 313 } 314 315 // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the 316 // ones requested from an already RLP encoded format. 317 func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error { 318 return p2p.Send(p.rw, ReceiptsMsg, receipts) 319 } 320 321 // RequestOneHeader is a wrapper around the header query functions to fetch a 322 // single header. It is used solely by the fetcher. 323 func (p *peer) RequestOneHeader(hash common.Hash) error { 324 p.Log().Debug("Fetching single header", "hash", hash) 325 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) 326 } 327 328 // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the 329 // specified header query, based on the hash of an origin block. 330 func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 331 p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) 332 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 333 } 334 335 // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the 336 // specified header query, based on the number of an origin block. 337 func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 338 p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) 339 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 340 } 341 342 // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes 343 // specified. 344 func (p *peer) RequestBodies(hashes []common.Hash) error { 345 p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) 346 return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) 347 } 348 349 // RequestNodeData fetches a batch of arbitrary data from a node's known state 350 // data, corresponding to the specified hashes. 351 func (p *peer) RequestNodeData(hashes []common.Hash) error { 352 p.Log().Debug("Fetching batch of state data", "count", len(hashes)) 353 return p2p.Send(p.rw, GetNodeDataMsg, hashes) 354 } 355 356 // RequestReceipts fetches a batch of transaction receipts from a remote node. 357 func (p *peer) RequestReceipts(hashes []common.Hash) error { 358 p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) 359 return p2p.Send(p.rw, GetReceiptsMsg, hashes) 360 } 361 362 // Handshake executes the eth protocol handshake, negotiating version number, 363 // network IDs, difficulties, head and genesis blocks. 364 func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter, protocolName string) error { 365 // Send out own handshake in a new thread 366 errc := make(chan error, 2) 367 368 var ( 369 status63 statusData63 // safe to read after two values have been received from errc 370 status statusData // safe to read after two values have been received from errc 371 istanbulOld = protocolName == "istanbul" && p.version == consensus.Istanbul64 372 istanbulNew = protocolName == "istanbul" && p.version == consensus.Istanbul99 373 ) 374 go func() { 375 switch { 376 case p.version == eth63 || istanbulOld: 377 errc <- p2p.Send(p.rw, StatusMsg, &statusData63{ 378 ProtocolVersion: uint32(p.version), 379 NetworkId: network, 380 TD: td, 381 CurrentBlock: head, 382 GenesisBlock: genesis, 383 }) 384 case p.version == eth64 || istanbulNew: 385 errc <- p2p.Send(p.rw, StatusMsg, &statusData{ 386 ProtocolVersion: uint32(p.version), 387 NetworkID: network, 388 TD: td, 389 Head: head, 390 Genesis: genesis, 391 ForkID: forkID, 392 }) 393 default: 394 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 395 } 396 }() 397 go func() { 398 switch { 399 case p.version == eth63 || istanbulOld: 400 errc <- p.readStatusLegacy(network, &status63, genesis) 401 case p.version == eth64 || istanbulNew: 402 errc <- p.readStatus(network, &status, genesis, forkFilter) 403 default: 404 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 405 } 406 }() 407 timeout := time.NewTimer(handshakeTimeout) 408 defer timeout.Stop() 409 for i := 0; i < 2; i++ { 410 select { 411 case err := <-errc: 412 if err != nil { 413 return err 414 } 415 case <-timeout.C: 416 return p2p.DiscReadTimeout 417 } 418 } 419 switch { 420 case p.version == eth63 || istanbulOld: 421 p.td, p.head = status63.TD, status63.CurrentBlock 422 case p.version == eth64 || istanbulNew: 423 p.td, p.head = status.TD, status.Head 424 default: 425 panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) 426 } 427 return nil 428 } 429 430 func (p *peer) readStatusLegacy(network uint64, status *statusData63, genesis common.Hash) error { 431 msg, err := p.rw.ReadMsg() 432 if err != nil { 433 return err 434 } 435 if msg.Code != StatusMsg { 436 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 437 } 438 if msg.Size > protocolMaxMsgSize { 439 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) 440 } 441 // Decode the handshake and make sure everything matches 442 if err := msg.Decode(&status); err != nil { 443 return errResp(ErrDecode, "msg %v: %v", msg, err) 444 } 445 if status.GenesisBlock != genesis { 446 return errResp(ErrGenesisMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) 447 } 448 if status.NetworkId != network { 449 return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkId, network) 450 } 451 if int(status.ProtocolVersion) != p.version { 452 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 453 } 454 return nil 455 } 456 457 func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash, forkFilter forkid.Filter) error { 458 msg, err := p.rw.ReadMsg() 459 if err != nil { 460 return err 461 } 462 if msg.Code != StatusMsg { 463 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 464 } 465 if msg.Size > protocolMaxMsgSize { 466 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) 467 } 468 // Decode the handshake and make sure everything matches 469 if err := msg.Decode(&status); err != nil { 470 return errResp(ErrDecode, "msg %v: %v", msg, err) 471 } 472 if status.NetworkID != network { 473 return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkID, network) 474 } 475 if int(status.ProtocolVersion) != p.version { 476 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 477 } 478 if status.Genesis != genesis { 479 return errResp(ErrGenesisMismatch, "%x (!= %x)", status.Genesis, genesis) 480 } 481 if err := forkFilter(status.ForkID); err != nil { 482 return errResp(ErrForkIDRejected, "%v", err) 483 } 484 return nil 485 } 486 487 // String implements fmt.Stringer. 488 func (p *peer) String() string { 489 return fmt.Sprintf("Peer %s [%s]", p.id, 490 fmt.Sprintf("eth/%2d", p.version), 491 ) 492 } 493 494 // peerSet represents the collection of active peers currently participating in 495 // the Ethereum sub-protocol. 496 type peerSet struct { 497 peers map[string]*peer 498 lock sync.RWMutex 499 closed bool 500 } 501 502 // newPeerSet creates a new peer set to track the active participants. 503 func newPeerSet() *peerSet { 504 return &peerSet{ 505 peers: make(map[string]*peer), 506 } 507 } 508 509 // Register injects a new peer into the working set, or returns an error if the 510 // peer is already known. If a new peer it registered, its broadcast loop is also 511 // started. 512 func (ps *peerSet) Register(p *peer) error { 513 ps.lock.Lock() 514 defer ps.lock.Unlock() 515 516 if ps.closed { 517 return errClosed 518 } 519 if _, ok := ps.peers[p.id]; ok { 520 return errAlreadyRegistered 521 } 522 ps.peers[p.id] = p 523 go p.broadcast() 524 525 return nil 526 } 527 528 // Unregister removes a remote peer from the active set, disabling any further 529 // actions to/from that particular entity. 530 func (ps *peerSet) Unregister(id string) error { 531 ps.lock.Lock() 532 defer ps.lock.Unlock() 533 534 p, ok := ps.peers[id] 535 if !ok { 536 return errNotRegistered 537 } 538 delete(ps.peers, id) 539 p.close() 540 541 return nil 542 } 543 544 // Peers returns all registered peers 545 func (ps *peerSet) Peers() map[string]*peer { 546 ps.lock.RLock() 547 defer ps.lock.RUnlock() 548 549 set := make(map[string]*peer) 550 for id, p := range ps.peers { 551 set[id] = p 552 } 553 return set 554 } 555 556 // Peer retrieves the registered peer with the given id. 557 func (ps *peerSet) Peer(id string) *peer { 558 ps.lock.RLock() 559 defer ps.lock.RUnlock() 560 561 return ps.peers[id] 562 } 563 564 // Len returns if the current number of peers in the set. 565 func (ps *peerSet) Len() int { 566 ps.lock.RLock() 567 defer ps.lock.RUnlock() 568 569 return len(ps.peers) 570 } 571 572 // PeersWithoutBlock retrieves a list of peers that do not have a given block in 573 // their set of known hashes. 574 func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer { 575 ps.lock.RLock() 576 defer ps.lock.RUnlock() 577 578 list := make([]*peer, 0, len(ps.peers)) 579 for _, p := range ps.peers { 580 if !p.knownBlocks.Contains(hash) { 581 list = append(list, p) 582 } 583 } 584 return list 585 } 586 587 // PeersWithoutTx retrieves a list of peers that do not have a given transaction 588 // in their set of known hashes. 589 func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer { 590 ps.lock.RLock() 591 defer ps.lock.RUnlock() 592 593 list := make([]*peer, 0, len(ps.peers)) 594 for _, p := range ps.peers { 595 if !p.knownTxs.Contains(hash) { 596 list = append(list, p) 597 } 598 } 599 return list 600 } 601 602 // BestPeer retrieves the known peer with the currently highest total difficulty. 603 func (ps *peerSet) BestPeer() *peer { 604 ps.lock.RLock() 605 defer ps.lock.RUnlock() 606 607 var ( 608 bestPeer *peer 609 bestTd *big.Int 610 ) 611 for _, p := range ps.peers { 612 if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 { 613 bestPeer, bestTd = p, td 614 } 615 } 616 return bestPeer 617 } 618 619 // Close disconnects all peers. 620 // No new peers can be registered after Close has returned. 621 func (ps *peerSet) Close() { 622 ps.lock.Lock() 623 defer ps.lock.Unlock() 624 625 for _, p := range ps.peers { 626 p.Disconnect(p2p.DiscQuitting) 627 } 628 ps.closed = true 629 }