github.com/aergoio/aergo@v1.3.1/p2p/actorwork.go (about)

     1  /**
     2   *  @file
     3   *  @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2p
     7  
     8  import (
     9  	"fmt"
    10  	"github.com/aergoio/aergo/p2p/p2pcommon"
    11  	"github.com/aergoio/etcd/raft/raftpb"
    12  	"reflect"
    13  	"time"
    14  
    15  	"github.com/aergoio/aergo-actor/actor"
    16  	"github.com/aergoio/aergo/internal/enc"
    17  	"github.com/aergoio/aergo/message"
    18  	"github.com/aergoio/aergo/p2p/p2putil"
    19  	"github.com/aergoio/aergo/types"
    20  )
    21  
    22  const (
    23  	// fetchTimeOut was copied from syncer package. it can be problem if these value become different
    24  	fetchTimeOut = time.Second * 100
    25  )
    26  
    27  // GetAddresses send getAddress request to other peer
    28  func (p2ps *P2P) GetAddresses(peerID types.PeerID, size uint32) bool {
    29  	remotePeer, ok := p2ps.pm.GetPeer(peerID)
    30  	if !ok {
    31  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Msg("Message addressRequest to Unknown peer, check if a bug")
    32  
    33  		return false
    34  	}
    35  	senderAddr := p2ps.SelfMeta().ToPeerAddress()
    36  	// createPolaris message data
    37  	req := &types.AddressesRequest{Sender: &senderAddr, MaxSize: 50}
    38  	remotePeer.SendMessage(p2ps.mf.NewMsgRequestOrder(true, p2pcommon.AddressesRequest, req))
    39  	return true
    40  }
    41  
    42  // GetBlockHeaders send request message to peer and
    43  func (p2ps *P2P) GetBlockHeaders(msg *message.GetBlockHeaders) bool {
    44  	remotePeer, exists := p2ps.pm.GetPeer(msg.ToWhom)
    45  	if !exists {
    46  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(msg.ToWhom)).Msg("Request to invalid peer")
    47  		return false
    48  	}
    49  
    50  	p2ps.Debug().Str(p2putil.LogPeerName, remotePeer.Name()).Interface("msg", msg).Msg("Sending Get block Header request")
    51  	// create message data
    52  	reqMsg := &types.GetBlockHeadersRequest{Hash: msg.Hash,
    53  		Height: msg.Height, Offset: msg.Offset, Size: msg.MaxSize, Asc: msg.Asc,
    54  	}
    55  	remotePeer.SendMessage(p2ps.mf.NewMsgRequestOrder(true, p2pcommon.GetBlockHeadersRequest, reqMsg))
    56  	return true
    57  }
    58  
    59  // GetBlocks send request message to peer and
    60  func (p2ps *P2P) GetBlocks(peerID types.PeerID, blockHashes []message.BlockHash) bool {
    61  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
    62  	if !exists {
    63  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Str(p2putil.LogProtoID, string(p2pcommon.GetBlocksRequest)).Msg("Message to Unknown peer, check if a bug")
    64  		return false
    65  	}
    66  	if len(blockHashes) == 0 {
    67  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Str(p2putil.LogProtoID, string(p2pcommon.GetBlocksRequest)).Msg("meaningless GetBlocks request with zero hash")
    68  		return false
    69  	}
    70  	p2ps.Debug().Str(p2putil.LogPeerName, remotePeer.Name()).Int(p2putil.LogBlkCount, len(blockHashes)).Str("first_hash", enc.ToString(blockHashes[0])).Msg("Sending Get block request")
    71  
    72  	hashes := make([][]byte, len(blockHashes))
    73  	for i, hash := range blockHashes {
    74  		hashes[i] = ([]byte)(hash)
    75  	}
    76  	// create message data
    77  	req := &types.GetBlockRequest{Hashes: hashes}
    78  
    79  	remotePeer.SendMessage(p2ps.mf.NewMsgRequestOrder(true, p2pcommon.GetBlocksRequest, req))
    80  	return true
    81  }
    82  
    83  // GetBlocksChunk send request message to peer and
    84  func (p2ps *P2P) GetBlocksChunk(context actor.Context, msg *message.GetBlockChunks) {
    85  	peerID := msg.ToWhom
    86  	blockHashes := msg.Hashes
    87  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
    88  	if !exists {
    89  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Str(p2putil.LogProtoID, p2pcommon.GetBlocksRequest.String()).Msg("Message to Unknown peer, check if a bug")
    90  		context.Respond(&message.GetBlockChunksRsp{Seq:msg.Seq, ToWhom: peerID, Err: fmt.Errorf("invalid peer")})
    91  		return
    92  	}
    93  	receiver := NewBlockReceiver(p2ps, remotePeer, msg.Seq, blockHashes, msg.TTL)
    94  	receiver.StartGet()
    95  }
    96  
    97  // GetBlockHashes send request message to peer and make response message for block hashes
    98  func (p2ps *P2P) GetBlockHashes(context actor.Context, msg *message.GetHashes) {
    99  	peerID := msg.ToWhom
   100  	// TODO
   101  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
   102  	if !exists {
   103  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Str(p2putil.LogProtoID, p2pcommon.GetHashesRequest.String()).Msg("Invalid peerID")
   104  		context.Respond(&message.GetHashesRsp{Seq:msg.Seq, Hashes: nil, PrevInfo: msg.PrevInfo, Count: 0, Err: message.PeerNotFoundError})
   105  		return
   106  	}
   107  	receiver := NewBlockHashesReceiver(p2ps, remotePeer, msg.Seq, msg, fetchTimeOut)
   108  	receiver.StartGet()
   109  }
   110  
   111  // GetBlockHashes send request message to peer and make response message for block hashes
   112  func (p2ps *P2P) GetBlockHashByNo(context actor.Context, msg *message.GetHashByNo) {
   113  	peerID := msg.ToWhom
   114  	// TODO
   115  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
   116  	if !exists {
   117  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Str(p2putil.LogProtoID, p2pcommon.GetHashByNoRequest.String()).Msg("Invalid peerID")
   118  		context.Respond(&message.GetHashByNoRsp{Seq:msg.Seq, Err: message.PeerNotFoundError})
   119  		return
   120  	}
   121  	receiver := NewBlockHashByNoReceiver(p2ps, remotePeer, msg.Seq, msg.BlockNo, fetchTimeOut)
   122  	receiver.StartGet()
   123  }
   124  
   125  // NotifyNewBlock send notice message of new block to a peer
   126  func (p2ps *P2P) NotifyNewBlock(newBlock message.NotifyNewBlock) bool {
   127  	req := &types.NewBlockNotice{
   128  		BlockHash: newBlock.Block.BlockHash(),
   129  		BlockNo:   newBlock.BlockNo}
   130  	msg := p2ps.mf.NewMsgBlkBroadcastOrder(req)
   131  
   132  	// sending new block notice (relay inv message is not need to every nodes)
   133  	skipped, sent := p2ps.prm.NotifyNewBlockMsg(msg, p2ps.pm.GetPeers())
   134  
   135  	p2ps.Debug().Int("skipped_cnt", skipped).Int("sent_cnt", sent).Str("hash", enc.ToString(newBlock.Block.BlockHash())).Msg("Notifying new block")
   136  	return true
   137  }
   138  
   139  // NotifyNewBlock send notice message of new block to a peer
   140  func (p2ps *P2P) NotifyBlockProduced(newBlock message.NotifyNewBlock) bool {
   141  	// TODO fill producerID
   142  	req := &types.BlockProducedNotice{ProducerID: nil, BlockNo: newBlock.BlockNo, Block: newBlock.Block}
   143  	msg := p2ps.mf.NewMsgBPBroadcastOrder(req)
   144  
   145  	skipped, sent := p2ps.prm.NotifyNewBlockMsg(msg, p2ps.pm.GetPeers())
   146  	// TODO filter to only contain bp and trusted node.
   147  	//for _, neighbor := range p2ps.pm.GetPeers() {
   148  	//	if neighbor != nil && neighbor.State() == types.RUNNING {
   149  	//		sent++
   150  	//		neighbor.SendMessage(msg)
   151  	//	} else {
   152  	//		skipped++
   153  	//	}
   154  	//}
   155  	p2ps.Debug().Int("skipped_cnt", skipped).Int("sent_cnt", sent).Str("hash", enc.ToString(newBlock.Block.BlockHash())).Uint64("block_no", req.BlockNo).Msg("Notifying block produced")
   156  	return true
   157  }
   158  
   159  // GetTXs send request message to peer and
   160  func (p2ps *P2P) GetTXs(peerID types.PeerID, txHashes []message.TXHash) bool {
   161  	remotePeer, ok := p2ps.pm.GetPeer(peerID)
   162  	if !ok {
   163  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Msg("Invalid peer. check for bug")
   164  		return false
   165  	}
   166  	if len(txHashes) == 0 {
   167  		p2ps.Warn().Msg("empty hash list")
   168  		return false
   169  	}
   170  
   171  	hashes := make([][]byte, len(txHashes))
   172  	for i, hash := range txHashes {
   173  		if len(hash) == 0 {
   174  			p2ps.Warn().Msg("empty hash value requested.")
   175  			return false
   176  		}
   177  		hashes[i] = ([]byte)(hash)
   178  	}
   179  	// create message data
   180  	req := &types.GetTransactionsRequest{Hashes: hashes}
   181  
   182  	remotePeer.SendMessage(p2ps.mf.NewMsgRequestOrder(true, p2pcommon.GetTXsRequest, req))
   183  	return true
   184  }
   185  
   186  // NotifyNewTX notice tx(s) id created
   187  func (p2ps *P2P) NotifyNewTX(newTXs notifyNewTXs) bool {
   188  	hashes := newTXs.ids
   189  	// create message data
   190  	skipped, sent := 0, 0
   191  	// send to peers
   192  	peers := p2ps.pm.GetPeers()
   193  	p2ps.tnt.RegisterTxNotice(hashes, len(peers), newTXs.alreadySent)
   194  	for _, rPeer := range peers {
   195  		if rPeer != nil && rPeer.State() == types.RUNNING {
   196  			sent++
   197  			rPeer.PushTxsNotice(hashes)
   198  		} else {
   199  			skipped++
   200  		}
   201  	}
   202  	//p2ps.Debug().Int("skippeer_cnt", skipped).Int("sendpeer_cnt", sent).Int("hash_cnt", len(hashes)).Msg("Notifying newTXs to peers")
   203  	if skipped > 0 {
   204  		p2ps.tnt.ReportNotSend(hashes, skipped)
   205  	}
   206  
   207  	return true
   208  }
   209  
   210  // GetSyncAncestor request remote peer to find ancestor
   211  func (p2ps *P2P) GetSyncAncestor(context actor.Context, msg *message.GetSyncAncestor) {
   212  	peerID := msg.ToWhom
   213  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
   214  	if !exists {
   215  		p2ps.Warn().Str(p2putil.LogPeerID, p2putil.ShortForm(peerID)).Msg("invalid peer id")
   216  		context.Respond(&message.GetSyncAncestorRsp{Seq: msg.Seq, Ancestor:nil})
   217  		return
   218  	}
   219  	if len(msg.Hashes) == 0 {
   220  		p2ps.Warn().Str(p2putil.LogPeerName, remotePeer.Name()).Msg("empty hash list received")
   221  		context.Respond(&message.GetSyncAncestorRsp{Seq: msg.Seq, Ancestor:nil})
   222  		return
   223  	}
   224  
   225  	// create message data
   226  	receiver := NewAncestorReceiver(p2ps, remotePeer, msg.Seq, msg.Hashes, fetchTimeOut)
   227  	receiver.StartGet()
   228  	return
   229  }
   230  
   231  func (p2ps *P2P) SendRaftMessage(context actor.Context, msg *message.SendRaft) {
   232  	body, ok := msg.Body.(raftpb.Message)
   233  	if !ok {
   234  		p2ps.Error().Str("actual", reflect.TypeOf(msg.Body).String() ).Msg("body is not raftpb.Message")
   235  		return
   236  	}
   237  	peerID := msg.ToWhom
   238  	remotePeer, exists := p2ps.pm.GetPeer(peerID)
   239  	if !exists {
   240  		// temporarily comment out warning log, since current http/p2p hybrid env can cause too much logs
   241  		p2ps.consacc.RaftAccessor().ReportUnreachable(peerID)
   242  		return
   243  	}
   244  	remotePeer.SendMessage(p2ps.mf.NewRaftMsgOrder(body.Type, &body))
   245  	// return success
   246  }