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  }