github.com/amazechain/amc@v0.1.3/internal/download/peer.go (about) 1 // Copyright 2022 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package download 18 19 import ( 20 "context" 21 "github.com/amazechain/amc/api/protocol/sync_proto" 22 "github.com/amazechain/amc/common" 23 "github.com/amazechain/amc/common/message" 24 "github.com/amazechain/amc/log" 25 "github.com/amazechain/amc/utils" 26 "github.com/holiman/uint256" 27 "github.com/libp2p/go-libp2p/core/peer" 28 "go.uber.org/zap" 29 "google.golang.org/protobuf/proto" 30 "math/rand" 31 "sync" 32 ) 33 34 // peerInfo 35 type peerInfo struct { 36 ID peer.ID 37 Number *uint256.Int 38 Difficulty *uint256.Int 39 } 40 41 type peersInfo struct { 42 ctx context.Context 43 cancel context.CancelFunc 44 lock sync.RWMutex 45 46 peers common.PeerMap 47 info map[peer.ID]peerInfo 48 } 49 50 func (p *peersInfo) findPeers(number *uint256.Int, count int) common.PeerSet { 51 p.lock.RLock() 52 defer p.lock.RUnlock() 53 set := common.PeerSet{} 54 ids := make(map[peer.ID]struct{}, count) 55 for i := 0; i < len(p.peers) && i < count; i++ { 56 for id, _ := range p.peers { 57 if _, ok := ids[id]; ok { 58 continue 59 } 60 //p.log.Infof("Compare downloader number : %v, peer id : %v, remote peer number: %v", number.Uint64(), id.String(), p.info[id].Number.Uint64()) 61 // Add 2 number as network delay 62 if peerInfo, ok := p.info[id]; ok && new(uint256.Int).AddUint64(peerInfo.Number, 2).Cmp(number) >= 0 { 63 ids[id] = struct{}{} 64 set = append(set, p.peers[id]) 65 } 66 } 67 } 68 log.Tracef("finded great than number %v peers count: %v, limit: %v", number.Uint64(), len(set), count) 69 return set 70 } 71 72 func (p peersInfo) get(id peer.ID) (common.Peer, bool) { 73 peer, ok := p.peers[id] 74 return peer, ok 75 } 76 77 func (p *peersInfo) update(id peer.ID, Number *uint256.Int, Difficulty *uint256.Int) { 78 p.lock.Lock() 79 defer p.lock.Unlock() 80 81 if peer, ok := p.info[id]; ok { 82 peer.Number = Number 83 peer.Difficulty = Difficulty 84 } else { 85 p.info[id] = peerInfo{ 86 ID: id, 87 Difficulty: Difficulty, 88 Number: Number, 89 } 90 } 91 } 92 93 func (p *peersInfo) drop(id peer.ID) { 94 p.lock.Lock() 95 defer p.lock.Unlock() 96 delete(p.info, id) 97 } 98 99 // peerInfoBroadcastLoop 100 func (p *peersInfo) peerInfoBroadcast(Number *uint256.Int) { 101 log.Debugf("start to broadcast peer info , number is :%v , peer count is %v", Number.Uint64(), len(p.peers)) 102 for _, peer := range p.peers { 103 msg := &sync_proto.SyncTask{ 104 Id: rand.Uint64(), 105 SyncType: sync_proto.SyncType_PeerInfoBroadcast, 106 Payload: &sync_proto.SyncTask_SyncPeerInfoBroadcast{ 107 SyncPeerInfoBroadcast: &sync_proto.SyncPeerInfoBroadcast{ 108 Number: utils.ConvertUint256IntToH256(Number), 109 Difficulty: utils.ConvertUint256IntToH256(uint256.NewInt(0)), 110 //todo 111 }, 112 }, 113 } 114 115 payload, _ := proto.Marshal(msg) 116 err := peer.WriteMsg(message.MsgDownloader, payload) 117 118 if err != nil { 119 log.Error("failed to sync peer info", zap.String("peer id", peer.ID().String()), zap.Error(err)) 120 } 121 } 122 } 123 124 func newPeersInfo(ctx context.Context, peers common.PeerMap) *peersInfo { 125 c, cancel := context.WithCancel(ctx) 126 return &peersInfo{ 127 ctx: c, 128 cancel: cancel, 129 peers: peers, 130 info: make(map[peer.ID]peerInfo), 131 } 132 }