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