github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+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/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/core/types" 28 "github.com/ethereum/go-ethereum/p2p" 29 "github.com/ethereum/go-ethereum/rlp" 30 "gopkg.in/fatih/set.v0" 31 ) 32 33 var ( 34 errClosed = errors.New("peer set is closed") 35 errAlreadyRegistered = errors.New("peer is already registered") 36 errNotRegistered = errors.New("peer is not registered") 37 ) 38 39 const ( 40 maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) 41 maxKnownBlocks = 1024 // Maximum block hashes to keep in the known list (prevent DOS) 42 handshakeTimeout = 5 * time.Second 43 ) 44 45 // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known 46 // about a connected peer. 47 type PeerInfo struct { 48 Version int `json:"version"` // Ethereum protocol version negotiated 49 Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain 50 Head string `json:"head"` // SHA3 hash of the peer's best owned block 51 } 52 53 type peer struct { 54 id string 55 56 *p2p.Peer 57 rw p2p.MsgReadWriter 58 59 version int // Protocol version negotiated 60 forkDrop *time.Timer // Timed connection dropper if forks aren't validated in time 61 62 head common.Hash 63 td *big.Int 64 lock sync.RWMutex 65 66 knownTxs *set.Set // Set of transaction hashes known to be known by this peer 67 knownBlocks *set.Set // Set of block hashes known to be known by this peer 68 } 69 70 func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 71 id := p.ID() 72 73 return &peer{ 74 Peer: p, 75 rw: rw, 76 version: version, 77 id: fmt.Sprintf("%x", id[:8]), 78 knownTxs: set.New(), 79 knownBlocks: set.New(), 80 } 81 } 82 83 // Info gathers and returns a collection of metadata known about a peer. 84 func (p *peer) Info() *PeerInfo { 85 hash, td := p.Head() 86 87 return &PeerInfo{ 88 Version: p.version, 89 Difficulty: td, 90 Head: hash.Hex(), 91 } 92 } 93 94 // Head retrieves a copy of the current head hash and total difficulty of the 95 // peer. 96 func (p *peer) Head() (hash common.Hash, td *big.Int) { 97 p.lock.RLock() 98 defer p.lock.RUnlock() 99 100 copy(hash[:], p.head[:]) 101 return hash, new(big.Int).Set(p.td) 102 } 103 104 // SetHead updates the head hash and total difficulty of the peer. 105 func (p *peer) SetHead(hash common.Hash, td *big.Int) { 106 p.lock.Lock() 107 defer p.lock.Unlock() 108 109 copy(p.head[:], hash[:]) 110 p.td.Set(td) 111 } 112 113 // MarkBlock marks a block as known for the peer, ensuring that the block will 114 // never be propagated to this particular peer. 115 func (p *peer) MarkBlock(hash common.Hash) { 116 // If we reached the memory allowance, drop a previously known block hash 117 for p.knownBlocks.Size() >= maxKnownBlocks { 118 p.knownBlocks.Pop() 119 } 120 p.knownBlocks.Add(hash) 121 } 122 123 // MarkTransaction marks a transaction as known for the peer, ensuring that it 124 // will never be propagated to this particular peer. 125 func (p *peer) MarkTransaction(hash common.Hash) { 126 // If we reached the memory allowance, drop a previously known transaction hash 127 for p.knownTxs.Size() >= maxKnownTxs { 128 p.knownTxs.Pop() 129 } 130 p.knownTxs.Add(hash) 131 } 132 133 // Send writes an RLP-encoded message with the given code. 134 // data should encode as an RLP list. 135 func (p *peer) Send(msgcode uint64, data interface{}) error { 136 return p2p.Send(p.rw, msgcode, data) 137 } 138 139 // SendTransactions sends transactions to the peer and includes the hashes 140 // in its transaction hash set for future reference. 141 func (p *peer) SendTransactions(txs types.Transactions) error { 142 for _, tx := range txs { 143 p.knownTxs.Add(tx.Hash()) 144 } 145 return p2p.Send(p.rw, TxMsg, txs) 146 } 147 148 // SendNewBlockHashes announces the availability of a number of blocks through 149 // a hash notification. 150 func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { 151 for _, hash := range hashes { 152 p.knownBlocks.Add(hash) 153 } 154 request := make(newBlockHashesData, len(hashes)) 155 for i := 0; i < len(hashes); i++ { 156 request[i].Hash = hashes[i] 157 request[i].Number = numbers[i] 158 } 159 return p2p.Send(p.rw, NewBlockHashesMsg, request) 160 } 161 162 // SendNewBlock propagates an entire block to a remote peer. 163 func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { 164 p.knownBlocks.Add(block.Hash()) 165 return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) 166 } 167 168 // SendBlockHeaders sends a batch of block headers to the remote peer. 169 func (p *peer) SendBlockHeaders(headers []*types.Header) error { 170 return p2p.Send(p.rw, BlockHeadersMsg, headers) 171 } 172 173 // SendBlockBodies sends a batch of block contents to the remote peer. 174 func (p *peer) SendBlockBodies(bodies []*blockBody) error { 175 return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) 176 } 177 178 // SendBlockBodiesRLP sends a batch of block contents to the remote peer from 179 // an already RLP encoded format. 180 func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error { 181 return p2p.Send(p.rw, BlockBodiesMsg, bodies) 182 } 183 184 // SendNodeDataRLP sends a batch of arbitrary internal data, corresponding to the 185 // hashes requested. 186 func (p *peer) SendNodeData(data [][]byte) error { 187 return p2p.Send(p.rw, NodeDataMsg, data) 188 } 189 190 // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the 191 // ones requested from an already RLP encoded format. 192 func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error { 193 return p2p.Send(p.rw, ReceiptsMsg, receipts) 194 } 195 196 // RequestOneHeader is a wrapper around the header query functions to fetch a 197 // single header. It is used solely by the fetcher. 198 func (p *peer) RequestOneHeader(hash common.Hash) error { 199 p.Log().Debug("Fetching single header", "hash", hash) 200 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) 201 } 202 203 // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the 204 // specified header query, based on the hash of an origin block. 205 func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 206 p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) 207 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 208 } 209 210 // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the 211 // specified header query, based on the number of an origin block. 212 func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 213 p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) 214 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 215 } 216 217 // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes 218 // specified. 219 func (p *peer) RequestBodies(hashes []common.Hash) error { 220 p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) 221 return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) 222 } 223 224 // RequestNodeData fetches a batch of arbitrary data from a node's known state 225 // data, corresponding to the specified hashes. 226 func (p *peer) RequestNodeData(hashes []common.Hash) error { 227 p.Log().Debug("Fetching batch of state data", "count", len(hashes)) 228 return p2p.Send(p.rw, GetNodeDataMsg, hashes) 229 } 230 231 // RequestReceipts fetches a batch of transaction receipts from a remote node. 232 func (p *peer) RequestReceipts(hashes []common.Hash) error { 233 p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) 234 return p2p.Send(p.rw, GetReceiptsMsg, hashes) 235 } 236 237 // Handshake executes the eth protocol handshake, negotiating version number, 238 // network IDs, difficulties, head and genesis blocks. 239 func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash) error { 240 // Send out own handshake in a new thread 241 errc := make(chan error, 2) 242 var status statusData // safe to read after two values have been received from errc 243 244 go func() { 245 errc <- p2p.Send(p.rw, StatusMsg, &statusData{ 246 ProtocolVersion: uint32(p.version), 247 NetworkId: network, 248 TD: td, 249 CurrentBlock: head, 250 GenesisBlock: genesis, 251 }) 252 }() 253 go func() { 254 errc <- p.readStatus(network, &status, genesis) 255 }() 256 timeout := time.NewTimer(handshakeTimeout) 257 defer timeout.Stop() 258 for i := 0; i < 2; i++ { 259 select { 260 case err := <-errc: 261 if err != nil { 262 return err 263 } 264 case <-timeout.C: 265 return p2p.DiscReadTimeout 266 } 267 } 268 p.td, p.head = status.TD, status.CurrentBlock 269 return nil 270 } 271 272 func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash) (err error) { 273 msg, err := p.rw.ReadMsg() 274 if err != nil { 275 return err 276 } 277 if msg.Code != StatusMsg { 278 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 279 } 280 if msg.Size > ProtocolMaxMsgSize { 281 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 282 } 283 // Decode the handshake and make sure everything matches 284 if err := msg.Decode(&status); err != nil { 285 return errResp(ErrDecode, "msg %v: %v", msg, err) 286 } 287 if status.GenesisBlock != genesis { 288 return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) 289 } 290 if status.NetworkId != network { 291 return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network) 292 } 293 if int(status.ProtocolVersion) != p.version { 294 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 295 } 296 return nil 297 } 298 299 // String implements fmt.Stringer. 300 func (p *peer) String() string { 301 return fmt.Sprintf("Peer %s [%s]", p.id, 302 fmt.Sprintf("eth/%2d", p.version), 303 ) 304 } 305 306 // peerSet represents the collection of active peers currently participating in 307 // the Ethereum sub-protocol. 308 type peerSet struct { 309 peers map[string]*peer 310 lock sync.RWMutex 311 closed bool 312 } 313 314 // newPeerSet creates a new peer set to track the active participants. 315 func newPeerSet() *peerSet { 316 return &peerSet{ 317 peers: make(map[string]*peer), 318 } 319 } 320 321 // Register injects a new peer into the working set, or returns an error if the 322 // peer is already known. 323 func (ps *peerSet) Register(p *peer) error { 324 ps.lock.Lock() 325 defer ps.lock.Unlock() 326 327 if ps.closed { 328 return errClosed 329 } 330 if _, ok := ps.peers[p.id]; ok { 331 return errAlreadyRegistered 332 } 333 ps.peers[p.id] = p 334 return nil 335 } 336 337 // Unregister removes a remote peer from the active set, disabling any further 338 // actions to/from that particular entity. 339 func (ps *peerSet) Unregister(id string) error { 340 ps.lock.Lock() 341 defer ps.lock.Unlock() 342 343 if _, ok := ps.peers[id]; !ok { 344 return errNotRegistered 345 } 346 delete(ps.peers, id) 347 return nil 348 } 349 350 // Peers returns all registered peers 351 func (ps *peerSet) Peers() map[string]*peer { 352 ps.lock.RLock() 353 defer ps.lock.RUnlock() 354 355 set := make(map[string]*peer) 356 for id, p := range ps.peers { 357 set[id] = p 358 } 359 return set 360 } 361 362 // Peer retrieves the registered peer with the given id. 363 func (ps *peerSet) Peer(id string) *peer { 364 ps.lock.RLock() 365 defer ps.lock.RUnlock() 366 367 return ps.peers[id] 368 } 369 370 // Len returns if the current number of peers in the set. 371 func (ps *peerSet) Len() int { 372 ps.lock.RLock() 373 defer ps.lock.RUnlock() 374 375 return len(ps.peers) 376 } 377 378 // PeersWithoutBlock retrieves a list of peers that do not have a given block in 379 // their set of known hashes. 380 func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer { 381 ps.lock.RLock() 382 defer ps.lock.RUnlock() 383 384 list := make([]*peer, 0, len(ps.peers)) 385 for _, p := range ps.peers { 386 if !p.knownBlocks.Has(hash) { 387 list = append(list, p) 388 } 389 } 390 return list 391 } 392 393 // PeersWithoutTx retrieves a list of peers that do not have a given transaction 394 // in their set of known hashes. 395 func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer { 396 ps.lock.RLock() 397 defer ps.lock.RUnlock() 398 399 list := make([]*peer, 0, len(ps.peers)) 400 for _, p := range ps.peers { 401 if !p.knownTxs.Has(hash) { 402 list = append(list, p) 403 } 404 } 405 return list 406 } 407 408 // BestPeer retrieves the known peer with the currently highest total difficulty. 409 func (ps *peerSet) BestPeer() *peer { 410 ps.lock.RLock() 411 defer ps.lock.RUnlock() 412 413 var ( 414 bestPeer *peer 415 bestTd *big.Int 416 ) 417 for _, p := range ps.peers { 418 if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 { 419 bestPeer, bestTd = p, td 420 } 421 } 422 return bestPeer 423 } 424 425 // Close disconnects all peers. 426 // No new peers can be registered after Close has returned. 427 func (ps *peerSet) Close() { 428 ps.lock.Lock() 429 defer ps.lock.Unlock() 430 431 for _, p := range ps.peers { 432 p.Disconnect(p2p.DiscQuitting) 433 } 434 ps.closed = true 435 }