github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/neatptc/peer.go (about) 1 package neatptc 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "sync" 8 "time" 9 10 "github.com/neatio-net/neatio/chain/consensus" 11 "github.com/neatio-net/wire-go" 12 13 "github.com/neatio-net/neatio/chain/core/types" 14 "github.com/neatio-net/neatio/network/p2p" 15 "github.com/neatio-net/neatio/utilities/common" 16 "github.com/neatio-net/neatio/utilities/rlp" 17 "github.com/neatio-net/set-go" 18 ) 19 20 var ( 21 errClosed = errors.New("peer set is closed") 22 errAlreadyRegistered = errors.New("peer is already registered") 23 errNotRegistered = errors.New("peer is not registered") 24 ) 25 26 const ( 27 maxKnownTxs = 32768 28 maxKnownBlocks = 1024 29 maxKnownTX3ProofData = 32768 30 handshakeTimeout = 5 * time.Second 31 ) 32 33 type PeerInfo struct { 34 Version int `json:"version"` 35 Difficulty *big.Int `json:"difficulty"` 36 Head string `json:"head"` 37 } 38 39 type peer struct { 40 id string 41 consensus_pub_key string 42 43 *p2p.Peer 44 rw p2p.MsgReadWriter 45 46 pname string 47 version int 48 forkDrop *time.Timer 49 50 head common.Hash 51 td *big.Int 52 lock sync.RWMutex 53 54 knownTxs *set.Set 55 knownBlocks *set.Set 56 knownTX3ProofDatas *set.Set 57 58 peerState consensus.PeerState 59 } 60 61 func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 62 id := p.ID() 63 64 return &peer{ 65 Peer: p, 66 rw: rw, 67 68 version: version, 69 id: fmt.Sprintf("%x", id[:8]), 70 knownTxs: set.New(), 71 knownBlocks: set.New(), 72 knownTX3ProofDatas: set.New(), 73 } 74 } 75 76 func (p *peer) Info() *PeerInfo { 77 hash, td := p.Head() 78 79 return &PeerInfo{ 80 Version: p.version, 81 Difficulty: td, 82 Head: hash.Hex(), 83 } 84 } 85 86 func (p *peer) GetConsensusKey() string { 87 return p.consensus_pub_key 88 } 89 90 func (p *peer) Head() (hash common.Hash, td *big.Int) { 91 p.lock.RLock() 92 defer p.lock.RUnlock() 93 94 copy(hash[:], p.head[:]) 95 return hash, new(big.Int).Set(p.td) 96 } 97 98 func (p *peer) SetHead(hash common.Hash, td *big.Int) { 99 p.lock.Lock() 100 defer p.lock.Unlock() 101 102 copy(p.head[:], hash[:]) 103 p.td.Set(td) 104 } 105 106 func (p *peer) MarkBlock(hash common.Hash) { 107 108 for p.knownBlocks.Size() >= maxKnownBlocks { 109 p.knownBlocks.Pop() 110 } 111 p.knownBlocks.Add(hash) 112 } 113 114 func (p *peer) MarkTransaction(hash common.Hash) { 115 116 for p.knownTxs.Size() >= maxKnownTxs { 117 p.knownTxs.Pop() 118 } 119 p.knownTxs.Add(hash) 120 } 121 122 func (p *peer) MarkTX3ProofData(hash common.Hash) { 123 124 for p.knownTX3ProofDatas.Size() >= maxKnownTX3ProofData { 125 p.knownTX3ProofDatas.Pop() 126 } 127 p.knownTX3ProofDatas.Add(hash) 128 } 129 130 func (p *peer) Send(msgcode uint64, data interface{}) error { 131 if msgcode >= 0x20 && msgcode <= 0x23 { 132 wirebytes := wire.BinaryBytes(data) 133 return p2p.Send(p.rw, msgcode, wirebytes) 134 } else { 135 return p2p.Send(p.rw, msgcode, data) 136 } 137 138 } 139 140 func (p *peer) GetPeerState() consensus.PeerState { 141 return p.peerState 142 } 143 144 func (p *peer) GetKey() string { 145 return p.id 146 } 147 148 func (p *peer) SetPeerState(ps consensus.PeerState) { 149 p.peerState = ps 150 } 151 152 func (p *peer) SendTransactions(txs types.Transactions) error { 153 for _, tx := range txs { 154 p.knownTxs.Add(tx.Hash()) 155 } 156 return p2p.Send(p.rw, TxMsg, txs) 157 } 158 159 func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { 160 for _, hash := range hashes { 161 p.knownBlocks.Add(hash) 162 } 163 request := make(newBlockHashesData, len(hashes)) 164 for i := 0; i < len(hashes); i++ { 165 request[i].Hash = hashes[i] 166 request[i].Number = numbers[i] 167 } 168 return p2p.Send(p.rw, NewBlockHashesMsg, request) 169 } 170 171 func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { 172 p.knownBlocks.Add(block.Hash()) 173 return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) 174 } 175 176 func (p *peer) SendBlockHeaders(headers []*types.Header) error { 177 return p2p.Send(p.rw, BlockHeadersMsg, headers) 178 } 179 180 func (p *peer) SendBlockBodies(bodies []*blockBody) error { 181 return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) 182 } 183 184 func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error { 185 return p2p.Send(p.rw, BlockBodiesMsg, bodies) 186 } 187 188 func (p *peer) SendNodeData(data [][]byte) error { 189 return p2p.Send(p.rw, NodeDataMsg, data) 190 } 191 192 func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error { 193 return p2p.Send(p.rw, ReceiptsMsg, receipts) 194 } 195 196 func (p *peer) SendTX3ProofData(proofDatas []*types.TX3ProofData) error { 197 for _, proofData := range proofDatas { 198 p.knownTX3ProofDatas.Add(proofData.Header.Hash()) 199 } 200 return p2p.Send(p.rw, TX3ProofDataMsg, proofDatas) 201 } 202 203 func (p *peer) SendPreimagesRLP(preimages [][]byte) error { 204 return p2p.Send(p.rw, PreImagesMsg, preimages) 205 } 206 207 func (p *peer) SendTrieNodeData(data [][]byte) error { 208 return p2p.Send(p.rw, TrieNodeDataMsg, data) 209 } 210 211 func (p *peer) RequestOneHeader(hash common.Hash) error { 212 p.Log().Debug("Fetching single header", "hash", hash) 213 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) 214 } 215 216 func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 217 p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) 218 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 219 } 220 221 func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 222 p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) 223 return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) 224 } 225 226 func (p *peer) RequestBodies(hashes []common.Hash) error { 227 p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) 228 return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) 229 } 230 231 func (p *peer) RequestNodeData(hashes []common.Hash) error { 232 p.Log().Debug("Fetching batch of state data", "count", len(hashes)) 233 return p2p.Send(p.rw, GetNodeDataMsg, hashes) 234 } 235 236 func (p *peer) RequestReceipts(hashes []common.Hash) error { 237 p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) 238 return p2p.Send(p.rw, GetReceiptsMsg, hashes) 239 } 240 241 func (p *peer) RequestPreimages(hashes []common.Hash) error { 242 p.Log().Debug("Fetching batch of preimages", "count", len(hashes)) 243 return p2p.Send(p.rw, GetPreImagesMsg, hashes) 244 } 245 246 func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash) error { 247 248 errc := make(chan error, 2) 249 var status statusData 250 251 go func() { 252 errc <- p2p.Send(p.rw, StatusMsg, &statusData{ 253 ProtocolVersion: uint32(p.version), 254 NetworkId: network, 255 TD: td, 256 CurrentBlock: head, 257 GenesisBlock: genesis, 258 }) 259 }() 260 go func() { 261 errc <- p.readStatus(network, &status, genesis) 262 }() 263 timeout := time.NewTimer(handshakeTimeout) 264 defer timeout.Stop() 265 for i := 0; i < 2; i++ { 266 select { 267 case err := <-errc: 268 if err != nil { 269 return err 270 } 271 case <-timeout.C: 272 return p2p.DiscReadTimeout 273 } 274 } 275 p.td, p.head = status.TD, status.CurrentBlock 276 return nil 277 } 278 279 func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash) (err error) { 280 msg, err := p.rw.ReadMsg() 281 if err != nil { 282 return err 283 } 284 if msg.Code != StatusMsg { 285 return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) 286 } 287 if msg.Size > ProtocolMaxMsgSize { 288 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 289 } 290 291 if err := msg.Decode(&status); err != nil { 292 return errResp(ErrDecode, "msg %v: %v", msg, err) 293 } 294 if status.GenesisBlock != genesis { 295 return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) 296 } 297 if status.NetworkId != network { 298 return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network) 299 } 300 if int(status.ProtocolVersion) != p.version { 301 return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) 302 } 303 return nil 304 } 305 306 func (p *peer) String() string { 307 return fmt.Sprintf("Peer %s [%s]", p.id, 308 fmt.Sprintf("%v/%2d", p.pname, p.version), 309 ) 310 } 311 312 type peerSet struct { 313 peers map[string]*peer 314 lock sync.RWMutex 315 closed bool 316 } 317 318 func newPeerSet() *peerSet { 319 return &peerSet{ 320 peers: make(map[string]*peer), 321 } 322 } 323 324 func (ps *peerSet) Register(p *peer) error { 325 ps.lock.Lock() 326 defer ps.lock.Unlock() 327 328 if ps.closed { 329 return errClosed 330 } 331 if _, ok := ps.peers[p.id]; ok { 332 return errAlreadyRegistered 333 } 334 ps.peers[p.id] = p 335 return nil 336 } 337 338 func (ps *peerSet) Unregister(id string) error { 339 ps.lock.Lock() 340 defer ps.lock.Unlock() 341 342 if _, ok := ps.peers[id]; !ok { 343 return errNotRegistered 344 } 345 delete(ps.peers, id) 346 return nil 347 } 348 349 func (ps *peerSet) Peers() map[string]*peer { 350 ps.lock.RLock() 351 defer ps.lock.RUnlock() 352 353 set := make(map[string]*peer) 354 for id, p := range ps.peers { 355 set[id] = p 356 } 357 return set 358 } 359 360 func (ps *peerSet) Peer(id string) *peer { 361 ps.lock.RLock() 362 defer ps.lock.RUnlock() 363 364 return ps.peers[id] 365 } 366 367 func (ps *peerSet) Len() int { 368 ps.lock.RLock() 369 defer ps.lock.RUnlock() 370 371 return len(ps.peers) 372 } 373 374 func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer { 375 ps.lock.RLock() 376 defer ps.lock.RUnlock() 377 378 list := make([]*peer, 0, len(ps.peers)) 379 for _, p := range ps.peers { 380 if !p.knownBlocks.Has(hash) { 381 list = append(list, p) 382 } 383 } 384 return list 385 } 386 387 func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer { 388 ps.lock.RLock() 389 defer ps.lock.RUnlock() 390 391 list := make([]*peer, 0, len(ps.peers)) 392 for _, p := range ps.peers { 393 if !p.knownTxs.Has(hash) { 394 list = append(list, p) 395 } 396 } 397 return list 398 } 399 400 func (ps *peerSet) PeersWithoutTX3ProofData(hash common.Hash) []*peer { 401 ps.lock.RLock() 402 defer ps.lock.RUnlock() 403 404 list := make([]*peer, 0, len(ps.peers)) 405 for _, p := range ps.peers { 406 if !p.knownTX3ProofDatas.Has(hash) { 407 list = append(list, p) 408 } 409 } 410 return list 411 } 412 413 func (ps *peerSet) BestPeer() *peer { 414 ps.lock.RLock() 415 defer ps.lock.RUnlock() 416 417 var ( 418 bestPeer *peer 419 bestTd *big.Int 420 ) 421 for _, p := range ps.peers { 422 if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 { 423 bestPeer, bestTd = p, td 424 } 425 } 426 return bestPeer 427 } 428 429 func (ps *peerSet) Close() { 430 ps.lock.Lock() 431 defer ps.lock.Unlock() 432 433 for _, p := range ps.peers { 434 p.Disconnect(p2p.DiscQuitting) 435 } 436 ps.closed = true 437 }