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 }