github.com/aergoio/aergo@v1.3.1/p2p/p2p.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/list" 11 "sync" 12 "time" 13 14 "github.com/aergoio/aergo/p2p/p2pkey" 15 "github.com/aergoio/aergo/p2p/raftsupport" 16 "github.com/aergoio/aergo/p2p/transport" 17 "github.com/rs/zerolog" 18 19 "github.com/aergoio/aergo/consensus" 20 "github.com/aergoio/aergo/internal/network" 21 "github.com/aergoio/aergo/p2p/metric" 22 "github.com/aergoio/aergo/p2p/p2pcommon" 23 "github.com/aergoio/aergo/p2p/p2putil" 24 "github.com/aergoio/aergo/p2p/subproto" 25 26 "github.com/aergoio/aergo-actor/actor" 27 "github.com/aergoio/aergo-lib/log" 28 "github.com/aergoio/aergo/chain" 29 "github.com/aergoio/aergo/config" 30 "github.com/aergoio/aergo/message" 31 "github.com/aergoio/aergo/pkg/component" 32 "github.com/aergoio/aergo/types" 33 ) 34 35 // P2P is actor component for p2p 36 type P2P struct { 37 *component.BaseComponent 38 39 cfg *config.Config 40 41 // inited during construction 42 useRaft bool 43 selfMeta p2pcommon.PeerMeta 44 // caching data from genesis block 45 chainID *types.ChainID 46 47 nt p2pcommon.NetworkTransport 48 pm p2pcommon.PeerManager 49 vm p2pcommon.VersionedManager 50 sm p2pcommon.SyncManager 51 mm metric.MetricsManager 52 mf p2pcommon.MoFactory 53 signer p2pcommon.MsgSigner 54 ca types.ChainAccessor 55 prm p2pcommon.PeerRoleManager 56 lm p2pcommon.ListManager 57 tnt *txNoticeTracer 58 59 mutex sync.Mutex 60 61 // inited between construction and start 62 consacc consensus.ConsensusAccessor 63 64 // inited after start 65 selfRole p2pcommon.PeerRole 66 } 67 68 var ( 69 _ p2pcommon.ActorService = (*P2P)(nil) 70 _ p2pcommon.HSHandlerFactory = (*P2P)(nil) 71 ) 72 73 // NewP2P create a new ActorService for p2p 74 func NewP2P(cfg *config.Config, chainSvc *chain.ChainService) *P2P { 75 p2psvc := &P2P{cfg: cfg} 76 p2psvc.BaseComponent = component.NewBaseComponent(message.P2PSvc, p2psvc, log.NewLogger("p2p")) 77 p2psvc.initP2P(chainSvc) 78 return p2psvc 79 } 80 81 func (p2ps *P2P) initP2P(chainSvc *chain.ChainService) { 82 cfg := p2ps.cfg 83 p2ps.ca = chainSvc 84 85 // check genesis block and get meta information from it 86 genesis := chainSvc.CDB().GetGenesisInfo() 87 chainIdBytes, err := genesis.ChainID() 88 if err != nil { 89 panic("genesis block is not set properly: " + err.Error()) 90 } 91 chainID := types.NewChainID() 92 err = chainID.Read(chainIdBytes) 93 if err != nil { 94 panic("invalid chainid: " + err.Error()) 95 } 96 p2ps.chainID = chainID 97 98 useRaft := genesis.ConsensusType() == consensus.ConsensusName[consensus.ConsensusRAFT] 99 p2ps.useRaft = useRaft 100 if p2ps.cfg.Consensus.EnableBp { 101 p2ps.selfRole = p2pcommon.BlockProducer 102 } else { 103 p2ps.selfRole = p2pcommon.Watcher 104 } 105 106 p2ps.selfMeta = SetupSelfMeta(p2pkey.NodeID(), cfg.P2P) 107 netTransport := transport.NewNetworkTransport(cfg.P2P, p2ps.Logger, p2ps) 108 signer := newDefaultMsgSigner(p2pkey.NodePrivKey(), p2pkey.NodePubKey(), p2pkey.NodeID()) 109 110 p2ps.tnt = newTxNoticeTracer(p2ps.Logger, p2ps) 111 mf := &baseMOFactory{p2ps: p2ps, tnt: p2ps.tnt} 112 113 if useRaft { 114 p2ps.prm = &RaftRoleManager{p2ps: p2ps, logger: p2ps.Logger, raftBP: make(map[types.PeerID]bool)} 115 } else { 116 p2ps.prm = &DefaultRoleManager{p2ps: p2ps} 117 } 118 119 // public network is always disabled white/blacklist in chain 120 lm := list.NewListManager(cfg.Auth, cfg.AuthDir, p2ps.ca, p2ps.prm, p2ps.Logger, genesis.PublicNet()) 121 metricMan := metric.NewMetricManager(10) 122 peerMan := NewPeerManager(p2ps, p2ps, p2ps, p2ps, netTransport, metricMan, lm, p2ps.Logger, cfg, useRaft) 123 syncMan := newSyncManager(p2ps, peerMan, p2ps.Logger) 124 versionMan := newDefaultVersionManager(peerMan, p2ps, p2ps.ca, p2ps.Logger, p2ps.chainID) 125 126 // connect managers each other 127 128 p2ps.mutex.Lock() 129 p2ps.signer = signer 130 p2ps.nt = netTransport 131 p2ps.mf = mf 132 p2ps.pm = peerMan 133 p2ps.vm = versionMan 134 p2ps.sm = syncMan 135 //p2ps.rm = reconMan 136 p2ps.mm = metricMan 137 p2ps.lm = lm 138 139 p2ps.mutex.Unlock() 140 } 141 142 // BeforeStart starts p2p service. 143 func (p2ps *P2P) BeforeStart() {} 144 145 func (p2ps *P2P) AfterStart() { 146 versions := make([]fmt.Stringer, len(AcceptedInboundVersions)) 147 for i, ver := range AcceptedInboundVersions { 148 versions[i] = ver 149 } 150 p2ps.lm.Start() 151 p2ps.mutex.Lock() 152 p2ps.checkConsensus() 153 p2ps.Logger.Info().Array("supportedVersions", p2putil.NewLogStringersMarshaller(versions, 10)).Str("role", p2ps.selfRole.String()).Msg("Starting p2p component") 154 nt := p2ps.nt 155 nt.Start() 156 p2ps.tnt.Start() 157 p2ps.mutex.Unlock() 158 159 if err := p2ps.pm.Start(); err != nil { 160 panic("Failed to start p2p component") 161 } 162 p2ps.mm.Start() 163 } 164 165 func (p2ps *P2P) checkConsensus() { 166 // set role of self peer 167 ccinfo := p2ps.consacc.ConsensusInfo() 168 if ccinfo.Type == "raft" { 169 if !p2ps.useRaft { 170 panic("configuration failure. consensus type of genesis block and consensus accessor are differ") 171 } 172 } 173 } 174 175 // BeforeStop is called before actor hub stops. it finishes underlying peer manager 176 func (p2ps *P2P) BeforeStop() { 177 p2ps.Logger.Debug().Msg("stopping p2p actor.") 178 p2ps.mm.Stop() 179 if err := p2ps.pm.Stop(); err != nil { 180 p2ps.Logger.Warn().Err(err).Msg("Error on stopping peerManager") 181 } 182 p2ps.mutex.Lock() 183 p2ps.tnt.Stop() 184 nt := p2ps.nt 185 p2ps.mutex.Unlock() 186 nt.Stop() 187 p2ps.lm.Stop() 188 } 189 190 // Statistics show statistic information of p2p module. NOTE: It it not implemented yet 191 func (p2ps *P2P) Statistics() *map[string]interface{} { 192 stmap := make(map[string]interface{}) 193 stmap["netstat"] = p2ps.mm.Summary() 194 stmap["config"] = p2ps.cfg.P2P 195 stmap["status"] = p2ps.selfMeta 196 wlSummary := p2ps.lm.Summary() 197 stmap["whitelist"] = wlSummary["whitelist"] 198 stmap["whitelist_on"] = wlSummary["whitelist_on"] 199 200 return &stmap 201 } 202 203 func (p2ps *P2P) GetNetworkTransport() p2pcommon.NetworkTransport { 204 p2ps.mutex.Lock() 205 defer p2ps.mutex.Unlock() 206 return p2ps.nt 207 } 208 209 func (p2ps *P2P) GetPeerAccessor() p2pcommon.PeerAccessor { 210 return p2ps 211 } 212 213 func (p2ps *P2P) SetConsensusAccessor(ca consensus.ConsensusAccessor) { 214 p2ps.consacc = ca 215 } 216 217 func (p2ps *P2P) ChainID() *types.ChainID { 218 return p2ps.chainID 219 } 220 221 // Receive got actor message and then handle it. 222 func (p2ps *P2P) Receive(context actor.Context) { 223 rawMsg := context.Message() 224 switch msg := rawMsg.(type) { 225 case *message.GetAddressesMsg: 226 p2ps.GetAddresses(msg.ToWhom, msg.Size) 227 case *message.GetMetrics: 228 context.Respond(p2ps.mm.Metrics()) 229 case *message.GetBlockHeaders: 230 p2ps.GetBlockHeaders(msg) 231 case *message.GetBlockChunks: 232 p2ps.GetBlocksChunk(context, msg) 233 case *message.GetBlockInfos: 234 p2ps.GetBlocks(msg.ToWhom, msg.Hashes) 235 case *message.GetHashes: 236 p2ps.GetBlockHashes(context, msg) 237 case *message.GetHashByNo: 238 p2ps.GetBlockHashByNo(context, msg) 239 case *message.NotifyNewBlock: 240 if msg.Produced { 241 p2ps.NotifyBlockProduced(*msg) 242 } else { 243 p2ps.NotifyNewBlock(*msg) 244 } 245 case *message.GetTransactions: 246 p2ps.GetTXs(msg.ToWhom, msg.Hashes) 247 case *message.NotifyNewTransactions: 248 hashes := make([]types.TxID, len(msg.Txs)) 249 for i, tx := range msg.Txs { 250 hashes[i] = types.ToTxID(tx.Hash) 251 } 252 p2ps.NotifyNewTX(notifyNewTXs{hashes, nil}) 253 case notifyNewTXs: 254 p2ps.NotifyNewTX(msg) 255 case *message.AddBlockRsp: 256 // do nothing for now. just for prevent deadletter 257 258 case *message.GetSelf: 259 context.Respond(p2ps.selfMeta) 260 case *message.GetPeers: 261 peers := p2ps.pm.GetPeerAddresses(msg.NoHidden, msg.ShowSelf) 262 context.Respond(&message.GetPeersRsp{Peers: peers}) 263 case *message.GetSyncAncestor: 264 p2ps.GetSyncAncestor(context, msg) 265 case *message.MapQueryMsg: 266 bestBlock, err := p2ps.GetChainAccessor().GetBestBlock() 267 if err == nil { 268 msg.BestBlock = bestBlock 269 p2ps.SendRequest(message.MapSvc, msg) 270 } 271 case *message.MapQueryRsp: 272 if msg.Err != nil { 273 p2ps.Logger.Info().Err(msg.Err).Msg("polaris returned error") 274 } else { 275 if len(msg.Peers) > 0 { 276 p2ps.checkAndAddPeerAddresses(msg.Peers) 277 } 278 } 279 case *message.GetCluster: 280 peers := p2ps.pm.GetPeers() 281 //clusterReceiver := raftsupport.NewClusterInfoReceiver(p2ps, p2ps.mf, peers, time.Second*5, msg) 282 clusterReceiver := raftsupport.NewConcClusterInfoReceiver(p2ps, p2ps.mf, peers, time.Second*5, msg, p2ps.Logger) 283 clusterReceiver.StartGet() 284 case *message.SendRaft: 285 p2ps.SendRaftMessage(context, msg) 286 case *message.RaftClusterEvent: 287 p2ps.Logger.Debug().Int("added", len(msg.BPAdded)).Int("removed", len(msg.BPRemoved)).Msg("bp changed") 288 p2ps.prm.UpdateBP(msg.BPAdded, msg.BPRemoved) 289 case message.GetRaftTransport: 290 context.Respond(raftsupport.NewAergoRaftTransport(p2ps.Logger, p2ps.nt, p2ps.pm, p2ps.mf, p2ps.consacc, msg.Cluster)) 291 case message.P2PWhiteListConfEnableEvent: 292 p2ps.Logger.Debug().Bool("enabled", msg.On).Msg("p2p whitelist on/off changed") 293 // TODO do more fine grained work 294 p2ps.lm.RefineList() 295 // disconnect newly blacklisted peer. 296 p2ps.checkAndBanInboundPeers() 297 case message.P2PWhiteListConfSetEvent: 298 p2ps.Logger.Debug().Array("entries", p2putil.NewLogStringsMarshaller(msg.Values, 10)).Msg("p2p whitelist entries changed") 299 // TODO do more fine grained work 300 p2ps.lm.RefineList() 301 // disconnect newly blacklisted peer. 302 p2ps.checkAndBanInboundPeers() 303 } 304 } 305 306 func (p2ps *P2P) checkAndBanInboundPeers() { 307 for _, peer := range p2ps.pm.GetPeers() { 308 // FIXME ip check should be currently connected ip address 309 ip, err := network.GetSingleIPAddress(peer.Meta().IPAddress) 310 if err != nil { 311 p2ps.Warn().Str(p2putil.LogPeerName, peer.Name()).Err(err).Msg("Failed to get ip address of peer") 312 continue 313 } 314 // TODO temporal treatment. need more works. 315 // just inbound peers will be disconnected 316 if peer.Meta().Outbound { 317 p2ps.Debug().Str(p2putil.LogPeerName, peer.Name()).Err(err).Msg("outbound peer is not banned") 318 continue 319 } 320 if banned, _ := p2ps.lm.IsBanned(ip.String(), peer.ID()); banned { 321 p2ps.Info().Str(p2putil.LogPeerName, peer.Name()).Msg("peer is banned by list manager") 322 peer.Stop() 323 } 324 } 325 } 326 327 // TODO need refactoring. this code is copied from subproto/addrs.go 328 func (p2ps *P2P) checkAndAddPeerAddresses(peers []*types.PeerAddress) { 329 selfPeerID := p2ps.SelfNodeID() 330 peerMetas := make([]p2pcommon.PeerMeta, 0, len(peers)) 331 for _, rPeerAddr := range peers { 332 rPeerID := types.PeerID(rPeerAddr.PeerID) 333 if selfPeerID == rPeerID { 334 continue 335 } 336 if network.CheckAddressType(rPeerAddr.Address) == network.AddressTypeError { 337 continue 338 } 339 meta := p2pcommon.FromPeerAddress(rPeerAddr) 340 peerMetas = append(peerMetas, meta) 341 } 342 if len(peerMetas) > 0 { 343 p2ps.pm.NotifyPeerAddressReceived(peerMetas) 344 } 345 } 346 347 // TellRequest implement interface method of ActorService 348 func (p2ps *P2P) TellRequest(actor string, msg interface{}) { 349 p2ps.TellTo(actor, msg) 350 } 351 352 // SendRequest implement interface method of ActorService 353 func (p2ps *P2P) SendRequest(actor string, msg interface{}) { 354 p2ps.RequestTo(actor, msg) 355 } 356 357 // FutureRequest implement interface method of ActorService 358 func (p2ps *P2P) FutureRequest(actor string, msg interface{}, timeout time.Duration) *actor.Future { 359 return p2ps.RequestToFuture(actor, msg, timeout) 360 } 361 362 // FutureRequestDefaultTimeout implement interface method of ActorService 363 func (p2ps *P2P) FutureRequestDefaultTimeout(actor string, msg interface{}) *actor.Future { 364 return p2ps.RequestToFuture(actor, msg, p2pcommon.DefaultActorMsgTTL) 365 } 366 367 // CallRequest implement interface method of ActorService 368 func (p2ps *P2P) CallRequest(actor string, msg interface{}, timeout time.Duration) (interface{}, error) { 369 future := p2ps.RequestToFuture(actor, msg, timeout) 370 return future.Result() 371 } 372 373 // CallRequest implement interface method of ActorService 374 func (p2ps *P2P) CallRequestDefaultTimeout(actor string, msg interface{}) (interface{}, error) { 375 future := p2ps.RequestToFuture(actor, msg, p2pcommon.DefaultActorMsgTTL) 376 return future.Result() 377 } 378 379 // GetChainAccessor implement interface method of ActorService 380 func (p2ps *P2P) GetChainAccessor() types.ChainAccessor { 381 return p2ps.ca 382 } 383 384 func (p2ps *P2P) insertHandlers(peer p2pcommon.RemotePeer) { 385 logger := p2ps.Logger 386 387 388 // PingHandlers 389 peer.AddMessageHandler(p2pcommon.PingRequest, subproto.NewPingReqHandler(p2ps.pm, peer, logger, p2ps)) 390 peer.AddMessageHandler(p2pcommon.PingResponse, subproto.NewPingRespHandler(p2ps.pm, peer, logger, p2ps)) 391 peer.AddMessageHandler(p2pcommon.GoAway, subproto.NewGoAwayHandler(p2ps.pm, peer, logger, p2ps)) 392 peer.AddMessageHandler(p2pcommon.AddressesRequest, subproto.NewAddressesReqHandler(p2ps.pm, peer, logger, p2ps)) 393 peer.AddMessageHandler(p2pcommon.AddressesResponse, subproto.NewAddressesRespHandler(p2ps.pm, peer, logger, p2ps)) 394 395 // BlockHandlers 396 peer.AddMessageHandler(p2pcommon.GetBlocksRequest, subproto.NewBlockReqHandler(p2ps.pm, peer, logger, p2ps)) 397 peer.AddMessageHandler(p2pcommon.GetBlocksResponse, subproto.NewBlockRespHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm)) 398 peer.AddMessageHandler(p2pcommon.GetBlockHeadersRequest, subproto.NewGetBlockHeadersReqHandler(p2ps.pm, peer, logger, p2ps)) 399 peer.AddMessageHandler(p2pcommon.GetBlockHeadersResponse, subproto.NewGetBlockHeaderRespHandler(p2ps.pm, peer, logger, p2ps)) 400 peer.AddMessageHandler(p2pcommon.GetAncestorRequest, subproto.NewGetAncestorReqHandler(p2ps.pm, peer, logger, p2ps)) 401 peer.AddMessageHandler(p2pcommon.GetAncestorResponse, subproto.NewGetAncestorRespHandler(p2ps.pm, peer, logger, p2ps)) 402 peer.AddMessageHandler(p2pcommon.GetHashesRequest, subproto.NewGetHashesReqHandler(p2ps.pm, peer, logger, p2ps)) 403 peer.AddMessageHandler(p2pcommon.GetHashesResponse, subproto.NewGetHashesRespHandler(p2ps.pm, peer, logger, p2ps)) 404 peer.AddMessageHandler(p2pcommon.GetHashByNoRequest, subproto.NewGetHashByNoReqHandler(p2ps.pm, peer, logger, p2ps)) 405 peer.AddMessageHandler(p2pcommon.GetHashByNoResponse, subproto.NewGetHashByNoRespHandler(p2ps.pm, peer, logger, p2ps)) 406 407 // TxHandlers 408 peer.AddMessageHandler(p2pcommon.GetTXsRequest, subproto.WithTimeLog(subproto.NewTxReqHandler(p2ps.pm, peer, logger, p2ps), p2ps.Logger, zerolog.DebugLevel)) 409 peer.AddMessageHandler(p2pcommon.GetTXsResponse, subproto.WithTimeLog(subproto.NewTxRespHandler(p2ps.pm, peer, logger, p2ps), p2ps.Logger, zerolog.DebugLevel)) 410 peer.AddMessageHandler(p2pcommon.NewTxNotice, subproto.WithTimeLog(subproto.NewNewTxNoticeHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm), p2ps.Logger, zerolog.DebugLevel)) 411 412 // block notice handlers 413 if p2ps.useRaft && p2ps.selfRole == p2pcommon.BlockProducer { 414 peer.AddMessageHandler(p2pcommon.BlockProducedNotice, subproto.NewBPNoticeDiscardHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm)) 415 peer.AddMessageHandler(p2pcommon.NewBlockNotice, subproto.NewBlkNoticeDiscardHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm)) 416 } else { 417 peer.AddMessageHandler(p2pcommon.BlockProducedNotice, subproto.WithTimeLog(subproto.NewBlockProducedNoticeHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm), p2ps.Logger, zerolog.DebugLevel)) 418 peer.AddMessageHandler(p2pcommon.NewBlockNotice, subproto.NewNewBlockNoticeHandler(p2ps.pm, peer, logger, p2ps, p2ps.sm)) 419 } 420 421 // Raft support 422 peer.AddMessageHandler(p2pcommon.GetClusterRequest, subproto.NewGetClusterReqHandler(p2ps.pm, peer, logger, p2ps, p2ps.consacc)) 423 peer.AddMessageHandler(p2pcommon.GetClusterResponse, subproto.NewGetClusterRespHandler(p2ps.pm, peer, logger, p2ps)) 424 peer.AddMessageHandler(p2pcommon.RaftWrapperMessage, subproto.NewRaftWrapperHandler(p2ps.pm, peer, logger, p2ps, p2ps.consacc)) 425 426 } 427 428 func (p2ps *P2P) CreateHSHandler(legacy bool, outbound bool, pid types.PeerID) p2pcommon.HSHandler { 429 if legacy { 430 handshakeHandler := newHandshaker(p2ps.pm, p2ps, p2ps.Logger, p2ps.chainID, pid) 431 if outbound { 432 return &LegacyOutboundHSHandler{LegacyWireHandshaker: handshakeHandler} 433 } else { 434 return &LegacyInboundHSHandler{LegacyWireHandshaker: handshakeHandler} 435 } 436 } else { 437 if outbound { 438 return NewOutboundHSHandler(p2ps.pm, p2ps, p2ps.vm, p2ps.Logger, p2ps.chainID, pid) 439 } else { 440 return NewInboundHSHandler(p2ps.pm, p2ps, p2ps.vm, p2ps.Logger, p2ps.chainID, pid) 441 } 442 } 443 } 444 445 func (p2ps *P2P) CreateRemotePeer(meta p2pcommon.PeerMeta, seq uint32, status *types.Status, stream types.Stream, rw p2pcommon.MsgReadWriter) p2pcommon.RemotePeer { 446 newPeer := newRemotePeer(meta, seq, p2ps.pm, p2ps, p2ps.Logger, p2ps.mf, p2ps.signer, rw) 447 newPeer.UpdateBlkCache(status.GetBestBlockHash(), status.GetBestHeight()) 448 newPeer.tnt = p2ps.tnt 449 rw.AddIOListener(p2ps.mm.NewMetric(newPeer.ID(), newPeer.ManageNumber())) 450 451 // TODO tune to set prefer role 452 newPeer.role = p2ps.prm.GetRole(meta.ID) 453 // insert Handlers 454 p2ps.insertHandlers(newPeer) 455 456 return newPeer 457 } 458 459 type notifyNewTXs struct { 460 ids []types.TxID 461 alreadySent []types.PeerID 462 } 463 464 func (p2ps *P2P) SelfMeta() p2pcommon.PeerMeta { 465 return p2ps.selfMeta 466 } 467 468 func (p2ps *P2P) SelfNodeID() types.PeerID { 469 return p2ps.selfMeta.ID 470 } 471 472 func (p2ps *P2P) SelfRole() p2pcommon.PeerRole { 473 return p2ps.selfRole 474 } 475 476 func (p2ps *P2P) GetPeerBlockInfos() []types.PeerBlockInfo { 477 return p2ps.pm.GetPeerBlockInfos() 478 } 479 480 func (p2ps *P2P) GetPeer(ID types.PeerID) (p2pcommon.RemotePeer, bool) { 481 return p2ps.pm.GetPeer(ID) 482 }