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  }