github.com/onflow/flow-go@v0.33.17/network/underlay/network.go (about) 1 package underlay 2 3 import ( 4 "bufio" 5 "context" 6 "errors" 7 "fmt" 8 "io" 9 "sync" 10 "time" 11 12 ggio "github.com/gogo/protobuf/io" 13 "github.com/ipfs/go-datastore" 14 libp2pnet "github.com/libp2p/go-libp2p/core/network" 15 "github.com/libp2p/go-libp2p/core/peer" 16 "github.com/libp2p/go-libp2p/core/peerstore" 17 "github.com/libp2p/go-libp2p/core/protocol" 18 "github.com/rs/zerolog" 19 20 "github.com/onflow/flow-go/model/flow" 21 "github.com/onflow/flow-go/model/flow/filter" 22 "github.com/onflow/flow-go/module" 23 "github.com/onflow/flow-go/module/component" 24 "github.com/onflow/flow-go/module/irrecoverable" 25 "github.com/onflow/flow-go/network" 26 alspmgr "github.com/onflow/flow-go/network/alsp/manager" 27 netcache "github.com/onflow/flow-go/network/cache" 28 "github.com/onflow/flow-go/network/channels" 29 "github.com/onflow/flow-go/network/codec" 30 "github.com/onflow/flow-go/network/internal/p2putils" 31 "github.com/onflow/flow-go/network/message" 32 "github.com/onflow/flow-go/network/p2p" 33 "github.com/onflow/flow-go/network/p2p/blob" 34 p2plogging "github.com/onflow/flow-go/network/p2p/logging" 35 "github.com/onflow/flow-go/network/p2p/ping" 36 "github.com/onflow/flow-go/network/p2p/subscription" 37 "github.com/onflow/flow-go/network/p2p/unicast/protocols" 38 "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" 39 "github.com/onflow/flow-go/network/p2p/utils" 40 "github.com/onflow/flow-go/network/queue" 41 "github.com/onflow/flow-go/network/underlay/internal" 42 "github.com/onflow/flow-go/network/validator" 43 flowpubsub "github.com/onflow/flow-go/network/validator/pubsub" 44 _ "github.com/onflow/flow-go/utils/binstat" 45 "github.com/onflow/flow-go/utils/logging" 46 ) 47 48 const ( 49 _ = iota 50 _ = 1 << (10 * iota) 51 mb 52 gb 53 ) 54 55 const ( 56 // DefaultMaxUnicastMsgSize defines maximum message size in unicast mode for most messages 57 DefaultMaxUnicastMsgSize = 10 * mb // 10 mb 58 59 // LargeMsgMaxUnicastMsgSize defines maximum message size in unicast mode for large messages 60 LargeMsgMaxUnicastMsgSize = gb // 1 gb 61 62 // DefaultUnicastTimeout is the default maximum time to wait for a default unicast request to complete 63 // assuming at least a 1mb/sec connection 64 DefaultUnicastTimeout = 5 * time.Second 65 66 // LargeMsgUnicastTimeout is the maximum time to wait for a unicast request to complete for large message size 67 LargeMsgUnicastTimeout = 1000 * time.Second 68 ) 69 70 var ( 71 // ErrUnicastMsgWithoutSub error is provided to the slashing violations consumer in the case where 72 // the network receives a message via unicast but does not have a corresponding subscription for 73 // the channel in that message. 74 ErrUnicastMsgWithoutSub = errors.New("networking layer does not have subscription for the channel ID indicated in the unicast message received") 75 ) 76 77 // NotEjectedFilter is an identity filter that, when applied to the identity 78 // table at a given snapshot, returns all nodes that we should communicate with 79 // over the networking layer. 80 // 81 // NOTE: The protocol state includes nodes from the previous/next epoch that should 82 // be included in network communication. We omit any nodes that have been ejected. 83 var NotEjectedFilter = filter.Not(filter.Ejected) 84 85 // Network serves as the comprehensive networking layer that integrates three interfaces within Flow; Underlay, EngineRegistry, and ConduitAdapter. 86 // It is responsible for creating conduits through which engines can send and receive messages to and from other engines on the network, as well as registering other services 87 // such as BlobService and PingService. It also provides a set of APIs that can be used to send messages to other nodes on the network. 88 // Network is also responsible for managing the topology of the network, i.e., the set of nodes that are connected to each other. 89 // It is also responsible for managing the set of nodes that are connected to each other. 90 type Network struct { 91 // TODO: using a waitgroup here doesn't actually guarantee that we'll wait for all 92 // goroutines to exit, because new goroutines could be started after we've already 93 // returned from wg.Wait(). We need to solve this the right way using ComponentManager 94 // and worker routines. 95 wg sync.WaitGroup 96 *component.ComponentManager 97 ctx context.Context 98 sporkId flow.Identifier 99 identityProvider module.IdentityProvider 100 identityTranslator p2p.IDTranslator 101 logger zerolog.Logger 102 codec network.Codec 103 me module.Local 104 metrics module.NetworkCoreMetrics 105 receiveCache *netcache.ReceiveCache // used to deduplicate incoming messages 106 queue network.MessageQueue 107 subscriptionManager network.SubscriptionManager // used to keep track of subscribed channels 108 conduitFactory network.ConduitFactory 109 topology network.Topology 110 registerEngineRequests chan *registerEngineRequest 111 registerBlobServiceRequests chan *registerBlobServiceRequest 112 misbehaviorReportManager network.MisbehaviorReportManager 113 unicastMessageTimeout time.Duration 114 libP2PNode p2p.LibP2PNode 115 bitswapMetrics module.BitswapMetrics 116 peerUpdateLock sync.Mutex // protects the peer update process 117 previousProtocolStatePeers []peer.AddrInfo 118 slashingViolationsConsumer network.ViolationsConsumer 119 peerManagerFilters []p2p.PeerFilter 120 unicastRateLimiters *ratelimit.RateLimiters 121 validators []network.MessageValidator 122 authorizedSenderValidator *validator.AuthorizedSenderValidator 123 preferredUnicasts []protocols.ProtocolName 124 } 125 126 var _ network.EngineRegistry = &Network{} 127 var _ network.Underlay = &Network{} 128 var _ network.ConduitAdapter = &Network{} 129 130 type registerEngineRequest struct { 131 channel channels.Channel 132 messageProcessor network.MessageProcessor 133 respChan chan *registerEngineResp 134 } 135 136 type registerEngineResp struct { 137 conduit network.Conduit 138 err error 139 } 140 141 type registerBlobServiceRequest struct { 142 channel channels.Channel 143 ds datastore.Batching 144 opts []network.BlobServiceOption 145 respChan chan *registerBlobServiceResp 146 } 147 148 type registerBlobServiceResp struct { 149 blobService network.BlobService 150 err error 151 } 152 153 var ErrNetworkShutdown = errors.New("network has already shutdown") 154 155 // NetworkConfig is a configuration struct for the network. It contains all the 156 // necessary components to create a new network. 157 type NetworkConfig struct { 158 Logger zerolog.Logger 159 Codec network.Codec 160 Me module.Local 161 Topology network.Topology 162 Metrics module.NetworkCoreMetrics 163 IdentityProvider module.IdentityProvider 164 IdentityTranslator p2p.IDTranslator 165 ReceiveCache *netcache.ReceiveCache 166 ConduitFactory network.ConduitFactory 167 AlspCfg *alspmgr.MisbehaviorReportManagerConfig 168 SporkId flow.Identifier 169 UnicastMessageTimeout time.Duration 170 Libp2pNode p2p.LibP2PNode 171 BitSwapMetrics module.BitswapMetrics 172 SlashingViolationConsumerFactory func(network.ConduitAdapter) network.ViolationsConsumer 173 } 174 175 // Validate validates the configuration, and sets default values for any missing fields. 176 func (cfg *NetworkConfig) Validate() { 177 if cfg.UnicastMessageTimeout <= 0 { 178 cfg.UnicastMessageTimeout = DefaultUnicastTimeout 179 } 180 } 181 182 // NetworkConfigOption is a function that can be used to override network config parmeters. 183 type NetworkConfigOption func(*NetworkConfig) 184 185 // WithAlspConfig overrides the default misbehavior report manager config. It is mostly used for testing purposes. 186 // Note: do not override the default misbehavior report manager config in production unless you know what you are doing. 187 // Args: 188 // cfg: misbehavior report manager config 189 // Returns: 190 // NetworkConfigOption: network param option 191 func WithAlspConfig(cfg *alspmgr.MisbehaviorReportManagerConfig) NetworkConfigOption { 192 return func(params *NetworkConfig) { 193 params.AlspCfg = cfg 194 } 195 } 196 197 // WithCodec overrides the default codec (i.e., encoder and decoder). It is mostly used for testing purposes. 198 // Note: do not override the default codec in production unless you know what you are doing. 199 func WithCodec(codec network.Codec) NetworkConfigOption { 200 return func(params *NetworkConfig) { 201 params.Codec = codec 202 } 203 } 204 205 func WithSlashingViolationConsumerFactory(factory func(adapter network.ConduitAdapter) network.ViolationsConsumer) NetworkConfigOption { 206 return func(params *NetworkConfig) { 207 params.SlashingViolationConsumerFactory = factory 208 } 209 } 210 211 // NetworkOption is a function that can be used to override network attributes. 212 // It is mostly used for testing purposes. 213 // Note: do not override network attributes in production unless you know what you are doing. 214 type NetworkOption func(*Network) 215 216 // WithAlspManager sets the misbehavior report manager for the network. It overrides the default 217 // misbehavior report manager that is created from the config. 218 // Note that this option is mostly used for testing purposes, do not use it in production unless you 219 // know what you are doing. 220 // 221 // Args: 222 // 223 // mgr: misbehavior report manager 224 // 225 // Returns: 226 // 227 // NetworkOption: network option 228 func WithAlspManager(mgr network.MisbehaviorReportManager) NetworkOption { 229 return func(n *Network) { 230 n.misbehaviorReportManager = mgr 231 } 232 } 233 234 // WithPeerManagerFilters sets the peer manager filters for the network. It overrides the default 235 // peer manager filters that are created from the config. 236 func WithPeerManagerFilters(filters ...p2p.PeerFilter) NetworkOption { 237 return func(n *Network) { 238 n.peerManagerFilters = filters 239 } 240 } 241 242 // WithUnicastRateLimiters sets the unicast rate limiters for the network. It overrides the default 243 // unicast rate limiters that are created from the config. 244 func WithUnicastRateLimiters(limiters *ratelimit.RateLimiters) NetworkOption { 245 return func(n *Network) { 246 n.unicastRateLimiters = limiters 247 } 248 } 249 250 // WithPreferredUnicastProtocols sets the preferred unicast protocols for the network. It overrides the default 251 // preferred unicast. 252 func WithPreferredUnicastProtocols(protocols ...protocols.ProtocolName) NetworkOption { 253 return func(n *Network) { 254 n.preferredUnicasts = protocols 255 } 256 } 257 258 // WithMessageValidators sets the message validators for the network. It overrides the default 259 // message validators. 260 func WithMessageValidators(validators ...network.MessageValidator) NetworkOption { 261 return func(n *Network) { 262 n.validators = validators 263 } 264 } 265 266 // NewNetwork creates a new network with the given configuration. 267 // Args: 268 // param: network configuration 269 // opts: network options 270 // Returns: 271 // Network: a new network 272 func NewNetwork(param *NetworkConfig, opts ...NetworkOption) (*Network, error) { 273 param.Validate() 274 275 n := &Network{ 276 logger: param.Logger.With().Str("component", "network").Logger(), 277 codec: param.Codec, 278 me: param.Me, 279 receiveCache: param.ReceiveCache, 280 topology: param.Topology, 281 metrics: param.Metrics, 282 bitswapMetrics: param.BitSwapMetrics, 283 identityProvider: param.IdentityProvider, 284 conduitFactory: param.ConduitFactory, 285 registerEngineRequests: make(chan *registerEngineRequest), 286 registerBlobServiceRequests: make(chan *registerBlobServiceRequest), 287 sporkId: param.SporkId, 288 identityTranslator: param.IdentityTranslator, 289 unicastMessageTimeout: param.UnicastMessageTimeout, 290 libP2PNode: param.Libp2pNode, 291 unicastRateLimiters: ratelimit.NoopRateLimiters(), 292 validators: DefaultValidators(param.Logger.With().Str("component", "network-validators").Logger(), param.Me.NodeID()), 293 } 294 295 n.subscriptionManager = subscription.NewChannelSubscriptionManager(n) 296 297 misbehaviorMngr, err := alspmgr.NewMisbehaviorReportManager(param.AlspCfg, n) 298 if err != nil { 299 return nil, fmt.Errorf("could not create misbehavior report manager: %w", err) 300 } 301 n.misbehaviorReportManager = misbehaviorMngr 302 303 for _, opt := range opts { 304 opt(n) 305 } 306 307 if err := n.conduitFactory.RegisterAdapter(n); err != nil { 308 return nil, fmt.Errorf("could not register network adapter: %w", err) 309 } 310 311 builder := component.NewComponentManagerBuilder() 312 builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 313 n.logger.Debug().Msg("starting misbehavior manager") 314 n.misbehaviorReportManager.Start(ctx) 315 316 select { 317 case <-n.misbehaviorReportManager.Ready(): 318 n.logger.Debug().Msg("misbehavior manager is ready") 319 ready() 320 case <-ctx.Done(): 321 // jumps to the end of the select statement to let a graceful shutdown. 322 } 323 324 <-ctx.Done() 325 n.logger.Debug().Msg("stopping misbehavior manager") 326 <-n.misbehaviorReportManager.Done() 327 n.logger.Debug().Msg("misbehavior manager stopped") 328 }) 329 builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 330 n.logger.Debug().Msg("setting up network context") 331 n.ctx = ctx 332 333 ready() 334 335 <-ctx.Done() 336 n.logger.Debug().Msg("network context is done") 337 }) 338 339 for _, limiter := range n.unicastRateLimiters.Limiters() { 340 rateLimiter := limiter 341 builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 342 ready() 343 rateLimiter.Start(ctx) 344 <-rateLimiter.Ready() 345 ready() 346 <-rateLimiter.Done() 347 }) 348 } 349 350 builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 351 // creation of slashing violations consumer should be postponed till here where the network 352 // is start and the overlay is set. 353 n.slashingViolationsConsumer = param.SlashingViolationConsumerFactory(n) 354 355 n.authorizedSenderValidator = validator.NewAuthorizedSenderValidator( 356 n.logger, 357 n.slashingViolationsConsumer, 358 n.Identity) 359 360 err := n.libP2PNode.WithDefaultUnicastProtocol(n.handleIncomingStream, n.preferredUnicasts) 361 if err != nil { 362 ctx.Throw(fmt.Errorf("could not register preferred unicast protocols on libp2p node: %w", err)) 363 } 364 365 n.UpdateNodeAddresses() 366 n.libP2PNode.WithPeersProvider(n.authorizedPeers) 367 368 ready() 369 370 <-ctx.Done() 371 n.logger.Info().Str("component", "network").Msg("stopping subroutines, blocking on read connection loops to end") 372 373 // wait for the readConnection and readSubscription routines to stop 374 n.wg.Wait() 375 n.logger.Info().Str("component", "network").Msg("stopped subroutines") 376 }) 377 378 builder.AddWorker(n.createInboundMessageQueue) 379 builder.AddWorker(n.processRegisterEngineRequests) 380 builder.AddWorker(n.processRegisterBlobServiceRequests) 381 382 n.ComponentManager = builder.Build() 383 return n, nil 384 } 385 386 func (n *Network) processRegisterEngineRequests(parent irrecoverable.SignalerContext, ready component.ReadyFunc) { 387 ready() 388 389 // we need to wait for the libp2p node to be ready before we can register engines 390 n.logger.Debug().Msg("waiting for libp2p node to be ready") 391 <-n.libP2PNode.Ready() 392 n.logger.Debug().Msg("libp2p node is ready") 393 394 for { 395 select { 396 case req := <-n.registerEngineRequests: 397 conduit, err := n.handleRegisterEngineRequest(parent, req.channel, req.messageProcessor) 398 resp := ®isterEngineResp{ 399 conduit: conduit, 400 err: err, 401 } 402 403 select { 404 case <-parent.Done(): 405 return 406 case req.respChan <- resp: 407 } 408 case <-parent.Done(): 409 return 410 } 411 } 412 } 413 414 func (n *Network) processRegisterBlobServiceRequests(parent irrecoverable.SignalerContext, ready component.ReadyFunc) { 415 ready() 416 417 n.logger.Debug().Msg("waiting for libp2p node to be ready") 418 <-n.libP2PNode.Ready() 419 n.logger.Debug().Msg("libp2p node is ready") 420 421 for { 422 select { 423 case req := <-n.registerBlobServiceRequests: 424 blobService, err := n.handleRegisterBlobServiceRequest(parent, req.channel, req.ds, req.opts) 425 resp := ®isterBlobServiceResp{ 426 blobService: blobService, 427 err: err, 428 } 429 430 select { 431 case <-parent.Done(): 432 return 433 case req.respChan <- resp: 434 } 435 case <-parent.Done(): 436 return 437 } 438 } 439 } 440 441 // createInboundMessageQueue creates the queue that will be used to process incoming messages. 442 func (n *Network) createInboundMessageQueue(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 443 n.queue = queue.NewMessageQueue(ctx, queue.GetEventPriority, n.metrics) 444 queue.CreateQueueWorkers(ctx, queue.DefaultNumWorkers, n.queue, n.queueSubmitFunc) 445 446 ready() 447 } 448 449 func (n *Network) handleRegisterEngineRequest(parent irrecoverable.SignalerContext, channel channels.Channel, engine network.MessageProcessor) (network.Conduit, error) { 450 if !channels.ChannelExists(channel) { 451 return nil, fmt.Errorf("unknown channel: %s, should be registered in topic map", channel) 452 } 453 454 err := n.subscriptionManager.Register(channel, engine) 455 if err != nil { 456 return nil, fmt.Errorf("failed to register engine for channel %s: %w", channel, err) 457 } 458 459 n.logger.Info(). 460 Str("channel_id", channel.String()). 461 Msg("channel successfully registered") 462 463 // create the conduit 464 newConduit, err := n.conduitFactory.NewConduit(parent, channel) 465 if err != nil { 466 return nil, fmt.Errorf("could not create conduit using factory: %w", err) 467 } 468 469 return newConduit, nil 470 } 471 472 func (n *Network) handleRegisterBlobServiceRequest(parent irrecoverable.SignalerContext, channel channels.Channel, ds datastore.Batching, opts []network.BlobServiceOption) (network.BlobService, 473 error) { 474 bs := blob.NewBlobService(n.libP2PNode.Host(), n.libP2PNode.Routing(), channel.String(), ds, n.bitswapMetrics, n.logger, opts...) 475 476 // start the blob service using the network's context 477 bs.Start(parent) 478 479 return bs, nil 480 } 481 482 // Register will register the given engine with the given unique engine engineID, 483 // returning a conduit to directly submit messages to the message bus of the 484 // engine. 485 func (n *Network) Register(channel channels.Channel, messageProcessor network.MessageProcessor) (network.Conduit, error) { 486 respChan := make(chan *registerEngineResp) 487 488 select { 489 case <-n.ComponentManager.ShutdownSignal(): 490 return nil, ErrNetworkShutdown 491 case n.registerEngineRequests <- ®isterEngineRequest{ 492 channel: channel, 493 messageProcessor: messageProcessor, 494 respChan: respChan, 495 }: 496 select { 497 case <-n.ComponentManager.ShutdownSignal(): 498 return nil, ErrNetworkShutdown 499 case resp := <-respChan: 500 return resp.conduit, resp.err 501 } 502 } 503 } 504 505 func (n *Network) RegisterPingService(pingProtocol protocol.ID, provider network.PingInfoProvider) (network.PingService, error) { 506 select { 507 case <-n.ComponentManager.ShutdownSignal(): 508 return nil, ErrNetworkShutdown 509 default: 510 return ping.NewPingService(n.libP2PNode.Host(), pingProtocol, n.logger, provider), nil 511 } 512 } 513 514 // RegisterBlobService registers a BlobService on the given channel. 515 // The returned BlobService can be used to request blobs from the network. 516 func (n *Network) RegisterBlobService(channel channels.Channel, ds datastore.Batching, opts ...network.BlobServiceOption) (network.BlobService, error) { 517 respChan := make(chan *registerBlobServiceResp) 518 519 select { 520 case <-n.ComponentManager.ShutdownSignal(): 521 return nil, ErrNetworkShutdown 522 case n.registerBlobServiceRequests <- ®isterBlobServiceRequest{ 523 channel: channel, 524 ds: ds, 525 opts: opts, 526 respChan: respChan, 527 }: 528 select { 529 case <-n.ComponentManager.ShutdownSignal(): 530 return nil, ErrNetworkShutdown 531 case resp := <-respChan: 532 return resp.blobService, resp.err 533 } 534 } 535 } 536 537 // UnRegisterChannel unregisters the engine for the specified channel. The engine will no longer be able to send or 538 // receive messages from that channel. 539 func (n *Network) UnRegisterChannel(channel channels.Channel) error { 540 err := n.subscriptionManager.Unregister(channel) 541 if err != nil { 542 return fmt.Errorf("failed to unregister engine for channel %s: %w", channel, err) 543 } 544 return nil 545 } 546 547 func (n *Network) Identities() flow.IdentityList { 548 return n.identityProvider.Identities(NotEjectedFilter) 549 } 550 551 func (n *Network) Identity(pid peer.ID) (*flow.Identity, bool) { 552 return n.identityProvider.ByPeerID(pid) 553 } 554 555 func (n *Network) Receive(msg network.IncomingMessageScope) error { 556 n.metrics.InboundMessageReceived(msg.Size(), msg.Channel().String(), msg.Protocol().String(), msg.PayloadType()) 557 558 err := n.processNetworkMessage(msg) 559 if err != nil { 560 return fmt.Errorf("could not process message: %w", err) 561 } 562 return nil 563 } 564 565 func (n *Network) processNetworkMessage(msg network.IncomingMessageScope) error { 566 // checks the cache for deduplication and adds the message if not already present 567 if !n.receiveCache.Add(msg.EventID()) { 568 // drops duplicate message 569 n.logger.Debug(). 570 Hex("sender_id", logging.ID(msg.OriginId())). 571 Hex("event_id", msg.EventID()). 572 Str("channel", msg.Channel().String()). 573 Msg("dropping message due to duplication") 574 575 n.metrics.DuplicateInboundMessagesDropped(msg.Channel().String(), msg.Protocol().String(), msg.PayloadType()) 576 577 return nil 578 } 579 580 // create queue message 581 qm := queue.QMessage{ 582 Payload: msg.DecodedPayload(), 583 Size: msg.Size(), 584 Target: msg.Channel(), 585 SenderID: msg.OriginId(), 586 } 587 588 // insert the message in the queue 589 err := n.queue.Insert(qm) 590 if err != nil { 591 return fmt.Errorf("failed to insert message in queue: %w", err) 592 } 593 594 return nil 595 } 596 597 // UnicastOnChannel sends the message in a reliable way to the given recipient. 598 // It uses 1-1 direct messaging over the underlying network to deliver the message. 599 // It returns an error if unicasting fails. 600 func (n *Network) UnicastOnChannel(channel channels.Channel, payload interface{}, targetID flow.Identifier) error { 601 if targetID == n.me.NodeID() { 602 n.logger.Debug().Msg("network skips self unicasting") 603 return nil 604 } 605 606 msg, err := message.NewOutgoingScope( 607 flow.IdentifierList{targetID}, 608 channels.TopicFromChannel(channel, n.sporkId), 609 payload, 610 n.codec.Encode, 611 message.ProtocolTypeUnicast) 612 if err != nil { 613 return fmt.Errorf("could not generate outgoing message scope for unicast: %w", err) 614 } 615 616 n.metrics.UnicastMessageSendingStarted(channel.String()) 617 defer n.metrics.UnicastMessageSendingCompleted(channel.String()) 618 619 // since it is a unicast, we only need to get the first peer ID. 620 peerID, err := n.identityTranslator.GetPeerID(msg.TargetIds()[0]) 621 if err != nil { 622 return fmt.Errorf("could not find peer id for target id: %w", err) 623 } 624 625 maxMsgSize := unicastMaxMsgSize(msg.PayloadType()) 626 if msg.Size() > maxMsgSize { 627 // message size goes beyond maximum size that the serializer can handle. 628 // proceeding with this message results in closing the connection by the target side, and 629 // delivery failure. 630 return fmt.Errorf("message size %d exceeds configured max message size %d", msg.Size(), maxMsgSize) 631 } 632 633 maxTimeout := n.unicastMaxMsgDuration(msg.PayloadType()) 634 635 // pass in a context with timeout to make the unicast call fail fast 636 ctx, cancel := context.WithTimeout(n.ctx, maxTimeout) 637 defer cancel() 638 639 // protect the underlying connection from being inadvertently pruned by the peer manager while the stream and 640 // connection creation is being attempted, and remove it from protected list once stream created. 641 channel, ok := channels.ChannelFromTopic(msg.Topic()) 642 if !ok { 643 return fmt.Errorf("could not find channel for topic %s", msg.Topic()) 644 } 645 streamProtectionTag := fmt.Sprintf("%v:%v", channel, msg.PayloadType()) 646 647 err = n.libP2PNode.OpenAndWriteOnStream(ctx, peerID, streamProtectionTag, func(stream libp2pnet.Stream) error { 648 bufw := bufio.NewWriter(stream) 649 writer := ggio.NewDelimitedWriter(bufw) 650 651 err = writer.WriteMsg(msg.Proto()) 652 if err != nil { 653 return fmt.Errorf("failed to send message to target id %x with peer id %s: %w", msg.TargetIds()[0], peerID, err) 654 } 655 656 // flush the stream 657 err = bufw.Flush() 658 if err != nil { 659 return fmt.Errorf("failed to flush stream for target id %x with peer id %s: %w", msg.TargetIds()[0], peerID, err) 660 } 661 662 return nil 663 }) 664 if err != nil { 665 return fmt.Errorf("failed to send message to %x: %w", targetID, err) 666 } 667 668 n.metrics.OutboundMessageSent(msg.Size(), channel.String(), message.ProtocolTypeUnicast.String(), msg.PayloadType()) 669 return nil 670 } 671 672 // PublishOnChannel sends the message in an unreliable way to the given recipients. 673 // In this context, unreliable means that the message is published over a libp2p pub-sub 674 // channel and can be read by any node subscribed to that channel. 675 // The selector could be used to optimize or restrict delivery. 676 func (n *Network) PublishOnChannel(channel channels.Channel, message interface{}, targetIDs ...flow.Identifier) error { 677 filteredIDs := flow.IdentifierList(targetIDs).Filter(n.removeSelfFilter()) 678 679 if len(filteredIDs) == 0 { 680 return fmt.Errorf("targetIDs %v: %w", len(targetIDs), network.EmptyTargetList) 681 } 682 683 err := n.sendOnChannel(channel, message, filteredIDs) 684 685 if err != nil { 686 return fmt.Errorf("failed to publish on channel %s: %w", channel, err) 687 } 688 689 return nil 690 } 691 692 // MulticastOnChannel unreliably sends the specified event over the channel to randomly selected 'num' number of recipients 693 // selected from the specified targetIDs. 694 func (n *Network) MulticastOnChannel(channel channels.Channel, message interface{}, num uint, targetIDs ...flow.Identifier) error { 695 selectedIDs, err := flow.IdentifierList(targetIDs).Filter(n.removeSelfFilter()).Sample(num) 696 if err != nil { 697 return fmt.Errorf("sampling failed: %w", err) 698 } 699 700 if len(selectedIDs) == 0 { 701 return fmt.Errorf("targetIDs %v: %w", len(targetIDs), network.EmptyTargetList) 702 } 703 704 err = n.sendOnChannel(channel, message, selectedIDs) 705 706 // publishes the message to the selected targets 707 if err != nil { 708 return fmt.Errorf("failed to multicast on channel %s: %w", channel, err) 709 } 710 711 return nil 712 } 713 714 // removeSelfFilter removes the flow.Identifier of this node if present, from the list of nodes 715 func (n *Network) removeSelfFilter() flow.IdentifierFilter { 716 return func(id flow.Identifier) bool { 717 return id != n.me.NodeID() 718 } 719 } 720 721 // sendOnChannel sends the message on channel to targets. 722 func (n *Network) sendOnChannel(channel channels.Channel, msg interface{}, targetIDs []flow.Identifier) error { 723 n.logger.Debug(). 724 Interface("message", msg). 725 Str("channel", channel.String()). 726 Str("target_ids", fmt.Sprintf("%v", targetIDs)). 727 Msg("sending new message on channel") 728 729 // generate network message (encoding) based on list of recipients 730 scope, err := message.NewOutgoingScope( 731 targetIDs, 732 channels.TopicFromChannel(channel, n.sporkId), 733 msg, 734 n.codec.Encode, 735 message.ProtocolTypePubSub) 736 if err != nil { 737 return fmt.Errorf("failed to generate outgoing message scope %s: %w", channel, err) 738 } 739 740 // publish the message through the channel, however, the message 741 // is only restricted to targetIDs (if they subscribed to channel). 742 err = n.libP2PNode.Publish(n.ctx, scope) 743 if err != nil { 744 return fmt.Errorf("failed to send message on channel %s: %w", channel, err) 745 } 746 747 n.metrics.OutboundMessageSent(scope.Size(), channel.String(), message.ProtocolTypePubSub.String(), scope.PayloadType()) 748 749 return nil 750 } 751 752 // queueSubmitFunc submits the message to the engine synchronously. It is the callback for the queue worker 753 // when it gets a message from the queue 754 func (n *Network) queueSubmitFunc(message interface{}) { 755 qm := message.(queue.QMessage) 756 757 logger := n.logger.With(). 758 Str("channel_id", qm.Target.String()). 759 Str("sender_id", qm.SenderID.String()). 760 Logger() 761 762 eng, err := n.subscriptionManager.GetEngine(qm.Target) 763 if err != nil { 764 // This means the message was received on a channel that the node has not registered an 765 // engine for. This may be because the message was received during startup and the node 766 // hasn't subscribed to the channel yet, or there is a bug. 767 logger.Err(err).Msg("failed to submit message") 768 return 769 } 770 771 logger.Debug().Msg("submitting message to engine") 772 773 n.metrics.MessageProcessingStarted(qm.Target.String()) 774 775 // submits the message to the engine synchronously and 776 // tracks its processing time. 777 startTimestamp := time.Now() 778 779 err = eng.Process(qm.Target, qm.SenderID, qm.Payload) 780 if err != nil { 781 logger.Err(err).Msg("failed to process message") 782 } 783 784 n.metrics.MessageProcessingFinished(qm.Target.String(), time.Since(startTimestamp)) 785 } 786 787 func (n *Network) Topology() flow.IdentityList { 788 return n.topology.Fanout(n.Identities()) 789 } 790 791 // ReportMisbehaviorOnChannel reports the misbehavior of a node on sending a message to the current node that appears 792 // valid based on the networking layer but is considered invalid by the current node based on the Flow protocol. 793 // The misbehavior report is sent to the current node's networking layer on the given channel to be processed. 794 // Args: 795 // - channel: The channel on which the misbehavior report is sent. 796 // - report: The misbehavior report to be sent. 797 // Returns: 798 // none 799 func (n *Network) ReportMisbehaviorOnChannel(channel channels.Channel, report network.MisbehaviorReport) { 800 n.misbehaviorReportManager.HandleMisbehaviorReport(channel, report) 801 } 802 803 func DefaultValidators(log zerolog.Logger, flowID flow.Identifier) []network.MessageValidator { 804 return []network.MessageValidator{ 805 validator.ValidateNotSender(flowID), // validator to filter out messages sent by this node itself 806 validator.ValidateTarget(log, flowID), // validator to filter out messages not intended for this node 807 } 808 } 809 810 // isProtocolParticipant returns a PeerFilter that returns true if a peer is a staked (i.e., authorized) node. 811 func (n *Network) isProtocolParticipant() p2p.PeerFilter { 812 return func(p peer.ID) error { 813 if _, ok := n.Identity(p); !ok { 814 return fmt.Errorf("failed to get identity of unknown peer with peer id %s", p2plogging.PeerId(p)) 815 } 816 return nil 817 } 818 } 819 820 func (n *Network) peerIDs(flowIDs flow.IdentifierList) peer.IDSlice { 821 result := make([]peer.ID, 0, len(flowIDs)) 822 823 for _, fid := range flowIDs { 824 pid, err := n.identityTranslator.GetPeerID(fid) 825 if err != nil { 826 // We probably don't need to fail the entire function here, since the other 827 // translations may still succeed 828 n.logger. 829 Err(err). 830 Str(logging.KeySuspicious, "true"). 831 Hex("node_id", logging.ID(fid)). 832 Msg("failed to translate to peer ID") 833 continue 834 } 835 836 result = append(result, pid) 837 } 838 839 return result 840 } 841 842 func (n *Network) UpdateNodeAddresses() { 843 n.logger.Info().Msg("updating protocol state node addresses") 844 845 ids := n.Identities() 846 newInfos, invalid := utils.PeerInfosFromIDs(ids) 847 848 for id, err := range invalid { 849 n.logger. 850 Err(err). 851 Bool(logging.KeySuspicious, true). 852 Hex("node_id", logging.ID(id)). 853 Msg("failed to extract peer info from identity") 854 } 855 856 n.peerUpdateLock.Lock() 857 defer n.peerUpdateLock.Unlock() 858 859 // set old addresses to expire 860 for _, oldInfo := range n.previousProtocolStatePeers { 861 n.libP2PNode.Host().Peerstore().SetAddrs(oldInfo.ID, oldInfo.Addrs, peerstore.TempAddrTTL) 862 } 863 864 for _, info := range newInfos { 865 n.libP2PNode.Host().Peerstore().SetAddrs(info.ID, info.Addrs, peerstore.PermanentAddrTTL) 866 } 867 868 n.previousProtocolStatePeers = newInfos 869 } 870 871 // authorizedPeers is a peer manager callback used by the underlying libp2p node that updates who can connect to this node (as 872 // well as who this node can connect to). 873 // and who is not allowed to connect to this node. This function is called by the peer manager and connection gater components 874 // of libp2p. 875 // 876 // Args: 877 // none 878 // Returns: 879 // - peer.IDSlice: a list of peer IDs that are allowed to connect to this node (and that this node can connect to). Any peer 880 // not in this list is assumed to be disconnected from this node (if connected) and not allowed to connect to this node. 881 // This is the guarantee that the underlying libp2p node implementation makes. 882 func (n *Network) authorizedPeers() peer.IDSlice { 883 peerIDs := make([]peer.ID, 0) 884 for _, id := range n.peerIDs(n.Topology().NodeIDs()) { 885 peerAllowed := true 886 for _, filter := range n.peerManagerFilters { 887 if err := filter(id); err != nil { 888 n.logger.Debug(). 889 Err(err). 890 Str("peer_id", p2plogging.PeerId(id)). 891 Msg("filtering topology peer") 892 893 peerAllowed = false 894 break 895 } 896 } 897 898 if peerAllowed { 899 peerIDs = append(peerIDs, id) 900 } 901 } 902 903 return peerIDs 904 } 905 906 func (n *Network) OnDisallowListNotification(notification *network.DisallowListingUpdate) { 907 for _, pid := range n.peerIDs(notification.FlowIds) { 908 n.libP2PNode.OnDisallowListNotification(pid, notification.Cause) 909 } 910 } 911 912 func (n *Network) OnAllowListNotification(notification *network.AllowListingUpdate) { 913 for _, pid := range n.peerIDs(notification.FlowIds) { 914 n.libP2PNode.OnAllowListNotification(pid, notification.Cause) 915 } 916 } 917 918 // handleIncomingStream handles an incoming stream from a remote peer 919 // it is a callback that gets called for each incoming stream by libp2p with a new stream object. 920 // TODO: this should be eventually moved to libp2p node. 921 func (n *Network) handleIncomingStream(s libp2pnet.Stream) { 922 // qualify the logger with local and remote address 923 log := p2putils.StreamLogger(n.logger, s) 924 925 log.Info().Msg("incoming stream received") 926 927 success := false 928 929 remotePeer := s.Conn().RemotePeer() 930 931 defer func() { 932 if success { 933 err := s.Close() 934 if err != nil { 935 log.Err(err).Msg("failed to close stream") 936 } 937 } else { 938 err := s.Reset() 939 if err != nil { 940 log.Err(err).Msg("failed to reset stream") 941 } 942 } 943 }() 944 945 // check if peer is currently rate limited before continuing to process stream. 946 if n.unicastRateLimiters.MessageRateLimiter.IsRateLimited(remotePeer) || n.unicastRateLimiters.BandWidthRateLimiter.IsRateLimited(remotePeer) { 947 log.Debug(). 948 Bool(logging.KeySuspicious, true). 949 Msg("dropping unicast stream from rate limited peer") 950 return 951 } 952 953 // TODO: We need to allow per-topic timeouts and message size limits. 954 // This allows us to configure higher limits for topics on which we expect 955 // to receive large messages (e.g. Chunk Data Packs), and use the normal 956 // limits for other topics. In order to enable this, we will need to register 957 // a separate stream handler for each topic. 958 ctx, cancel := context.WithTimeout(n.ctx, LargeMsgUnicastTimeout) 959 defer cancel() 960 961 deadline, _ := ctx.Deadline() 962 963 err := s.SetReadDeadline(deadline) 964 if err != nil { 965 log.Err(err).Msg("failed to set read deadline for stream") 966 return 967 } 968 969 // create the reader 970 r := ggio.NewDelimitedReader(s, LargeMsgMaxUnicastMsgSize) 971 for { 972 if ctx.Err() != nil { 973 return 974 } 975 976 // Note: message fields must not be trusted until explicitly validated 977 var msg message.Message 978 // read the next message (blocking call) 979 err = r.ReadMsg(&msg) 980 if err != nil { 981 if err == io.EOF { 982 break 983 } 984 985 n.logger.Err(err).Msg("failed to read message") 986 return 987 } 988 989 channel := channels.Channel(msg.ChannelID) 990 topic := channels.TopicFromChannel(channel, n.sporkId) 991 992 // ignore messages if node does not have subscription to topic 993 if !n.libP2PNode.HasSubscription(topic) { 994 violation := &network.Violation{ 995 Identity: nil, PeerID: p2plogging.PeerId(remotePeer), Channel: channel, Protocol: message.ProtocolTypeUnicast, 996 } 997 998 msgCode, err := codec.MessageCodeFromPayload(msg.Payload) 999 if err != nil { 1000 violation.Err = err 1001 n.slashingViolationsConsumer.OnUnknownMsgTypeError(violation) 1002 return 1003 } 1004 1005 // msg type is not guaranteed to be correct since it is set by the client 1006 _, what, err := codec.InterfaceFromMessageCode(msgCode) 1007 if err != nil { 1008 violation.Err = err 1009 n.slashingViolationsConsumer.OnUnknownMsgTypeError(violation) 1010 return 1011 } 1012 1013 violation.MsgType = what 1014 violation.Err = ErrUnicastMsgWithoutSub 1015 n.slashingViolationsConsumer.OnUnauthorizedUnicastOnChannel(violation) 1016 return 1017 } 1018 1019 // check if unicast messages have reached rate limit before processing next message 1020 if !n.unicastRateLimiters.MessageAllowed(remotePeer) { 1021 return 1022 } 1023 1024 // check if we can get a role for logging and metrics label if this is not a public channel 1025 role := "" 1026 if !channels.IsPublicChannel(channels.Channel(msg.ChannelID)) { 1027 if identity, ok := n.Identity(remotePeer); ok { 1028 role = identity.Role.String() 1029 } 1030 } 1031 1032 // check unicast bandwidth rate limiter for peer 1033 if !n.unicastRateLimiters.BandwidthAllowed( 1034 remotePeer, 1035 role, 1036 msg.Size(), 1037 message.MessageType(msg.Payload), 1038 channels.Topic(msg.ChannelID)) { 1039 return 1040 } 1041 1042 n.wg.Add(1) 1043 go func() { 1044 defer n.wg.Done() 1045 n.processUnicastStreamMessage(remotePeer, &msg) 1046 }() 1047 } 1048 1049 success = true 1050 } 1051 1052 // Subscribe subscribes the network to a channel. 1053 // No errors are expected during normal operation. 1054 func (n *Network) Subscribe(channel channels.Channel) error { 1055 topic := channels.TopicFromChannel(channel, n.sporkId) 1056 1057 var peerFilter p2p.PeerFilter 1058 var validators []validator.PubSubMessageValidator 1059 if channels.IsPublicChannel(channel) { 1060 // NOTE: for public channels the callback used to check if a node is staked will 1061 // return true for every node. 1062 peerFilter = p2p.AllowAllPeerFilter() 1063 } else { 1064 // for channels used by the staked nodes, add the topic validator to filter out messages from non-staked nodes 1065 validators = append(validators, n.authorizedSenderValidator.PubSubMessageValidator(channel)) 1066 1067 // NOTE: For non-public channels the libP2P node topic validator will reject 1068 // messages from unstaked nodes. 1069 peerFilter = n.isProtocolParticipant() 1070 } 1071 1072 topicValidator := flowpubsub.TopicValidator(n.logger, peerFilter, validators...) 1073 s, err := n.libP2PNode.Subscribe(topic, topicValidator) 1074 if err != nil { 1075 return fmt.Errorf("could not subscribe to topic (%s): %w", topic, err) 1076 } 1077 1078 // create a new readSubscription with the context of the network 1079 rs := internal.NewReadSubscription(s, n.processPubSubMessages, n.logger) 1080 n.wg.Add(1) 1081 1082 // kick off the receive loop to continuously receive messages 1083 go func() { 1084 defer n.wg.Done() 1085 rs.ReceiveLoop(n.ctx) 1086 }() 1087 1088 // update peers to add some nodes interested in the same topic as direct peers 1089 n.libP2PNode.RequestPeerUpdate() 1090 1091 return nil 1092 } 1093 1094 // processPubSubMessages processes messages received from the pubsub subscription. 1095 func (n *Network) processPubSubMessages(msg *message.Message, peerID peer.ID) { 1096 n.processAuthenticatedMessage(msg, peerID, message.ProtocolTypePubSub) 1097 } 1098 1099 // Unsubscribe unsubscribes the network from a channel. 1100 // The following benign errors are expected during normal operations from libP2P: 1101 // - the libP2P node fails to unsubscribe to the topic created from the provided channel. 1102 // 1103 // All errors returned from this function can be considered benign. 1104 func (n *Network) Unsubscribe(channel channels.Channel) error { 1105 topic := channels.TopicFromChannel(channel, n.sporkId) 1106 return n.libP2PNode.Unsubscribe(topic) 1107 } 1108 1109 // processUnicastStreamMessage will decode, perform authorized sender validation and process a message 1110 // sent via unicast stream. This func should be invoked in a separate goroutine to avoid creating a message decoding bottleneck. 1111 func (n *Network) processUnicastStreamMessage(remotePeer peer.ID, msg *message.Message) { 1112 channel := channels.Channel(msg.ChannelID) 1113 1114 // TODO: once we've implemented per topic message size limits per the TODO above, 1115 // we can remove this check 1116 maxSize, err := UnicastMaxMsgSizeByCode(msg.Payload) 1117 if err != nil { 1118 n.slashingViolationsConsumer.OnUnknownMsgTypeError(&network.Violation{ 1119 Identity: nil, PeerID: p2plogging.PeerId(remotePeer), MsgType: "", Channel: channel, Protocol: message.ProtocolTypeUnicast, Err: err, 1120 }) 1121 return 1122 } 1123 if msg.Size() > maxSize { 1124 // message size exceeded 1125 n.logger.Error(). 1126 Str("peer_id", p2plogging.PeerId(remotePeer)). 1127 Str("channel", msg.ChannelID). 1128 Int("max_size", maxSize). 1129 Int("size", msg.Size()). 1130 Bool(logging.KeySuspicious, true). 1131 Msg("received message exceeded permissible message maxSize") 1132 return 1133 } 1134 1135 // if message channel is not public perform authorized sender validation 1136 if !channels.IsPublicChannel(channel) { 1137 messageType, err := n.authorizedSenderValidator.Validate(remotePeer, msg.Payload, channel, message.ProtocolTypeUnicast) 1138 if err != nil { 1139 n.logger. 1140 Error(). 1141 Err(err). 1142 Str("peer_id", p2plogging.PeerId(remotePeer)). 1143 Str("type", messageType). 1144 Str("channel", msg.ChannelID). 1145 Msg("unicast authorized sender validation failed") 1146 return 1147 } 1148 } 1149 n.processAuthenticatedMessage(msg, remotePeer, message.ProtocolTypeUnicast) 1150 } 1151 1152 // processAuthenticatedMessage processes a message and a source (indicated by its peer ID) and eventually passes it to the overlay 1153 // In particular, it populates the `OriginID` field of the message with a Flow ID translated from this source. 1154 func (n *Network) processAuthenticatedMessage(msg *message.Message, peerID peer.ID, protocol message.ProtocolType) { 1155 originId, err := n.identityTranslator.GetFlowID(peerID) 1156 if err != nil { 1157 // this error should never happen. by the time the message gets here, the peer should be 1158 // authenticated which means it must be known 1159 n.logger.Error(). 1160 Err(err). 1161 Str("peer_id", p2plogging.PeerId(peerID)). 1162 Bool(logging.KeySuspicious, true). 1163 Msg("dropped message from unknown peer") 1164 return 1165 } 1166 1167 channel := channels.Channel(msg.ChannelID) 1168 decodedMsgPayload, err := n.codec.Decode(msg.Payload) 1169 switch { 1170 case codec.IsErrUnknownMsgCode(err): 1171 // slash peer if message contains unknown message code byte 1172 violation := &network.Violation{ 1173 PeerID: p2plogging.PeerId(peerID), OriginID: originId, Channel: channel, Protocol: protocol, Err: err, 1174 } 1175 n.slashingViolationsConsumer.OnUnknownMsgTypeError(violation) 1176 return 1177 case codec.IsErrMsgUnmarshal(err) || codec.IsErrInvalidEncoding(err): 1178 // slash if peer sent a message that could not be marshalled into the message type denoted by the message code byte 1179 violation := &network.Violation{ 1180 PeerID: p2plogging.PeerId(peerID), OriginID: originId, Channel: channel, Protocol: protocol, Err: err, 1181 } 1182 n.slashingViolationsConsumer.OnInvalidMsgError(violation) 1183 return 1184 case err != nil: 1185 // this condition should never happen and indicates there's a bug 1186 // don't crash as a result of external inputs since that creates a DoS vector 1187 // collect slashing data because this could potentially lead to slashing 1188 err = fmt.Errorf("unexpected error during message validation: %w", err) 1189 violation := &network.Violation{ 1190 PeerID: p2plogging.PeerId(peerID), OriginID: originId, Channel: channel, Protocol: protocol, Err: err, 1191 } 1192 n.slashingViolationsConsumer.OnUnexpectedError(violation) 1193 return 1194 } 1195 1196 scope, err := message.NewIncomingScope(originId, protocol, msg, decodedMsgPayload) 1197 if err != nil { 1198 n.logger.Error(). 1199 Err(err). 1200 Str("peer_id", p2plogging.PeerId(peerID)). 1201 Str("origin_id", originId.String()). 1202 Msg("could not create incoming message scope") 1203 return 1204 } 1205 1206 n.processMessage(scope) 1207 } 1208 1209 // processMessage processes a message and eventually passes it to the overlay 1210 func (n *Network) processMessage(scope network.IncomingMessageScope) { 1211 logger := n.logger.With(). 1212 Str("channel", scope.Channel().String()). 1213 Str("type", scope.Protocol().String()). 1214 Int("msg_size", scope.Size()). 1215 Hex("origin_id", logging.ID(scope.OriginId())). 1216 Logger() 1217 1218 // run through all the message validators 1219 for _, v := range n.validators { 1220 // if any one fails, stop message propagation 1221 if !v.Validate(scope) { 1222 logger.Debug().Msg("new message filtered by message validators") 1223 return 1224 } 1225 } 1226 1227 logger.Debug().Msg("processing new message") 1228 1229 // if validation passed, send the message to the overlay 1230 err := n.Receive(scope) 1231 if err != nil { 1232 n.logger.Error().Err(err).Msg("could not deliver payload") 1233 } 1234 } 1235 1236 // UnicastMaxMsgSizeByCode returns the max permissible size for a unicast message code 1237 func UnicastMaxMsgSizeByCode(payload []byte) (int, error) { 1238 msgCode, err := codec.MessageCodeFromPayload(payload) 1239 if err != nil { 1240 return 0, err 1241 } 1242 _, messageType, err := codec.InterfaceFromMessageCode(msgCode) 1243 if err != nil { 1244 return 0, err 1245 } 1246 1247 maxSize := unicastMaxMsgSize(messageType) 1248 return maxSize, nil 1249 } 1250 1251 // unicastMaxMsgSize returns the max permissible size for a unicast message 1252 func unicastMaxMsgSize(messageType string) int { 1253 switch messageType { 1254 case "*messages.ChunkDataResponse", "messages.ChunkDataResponse": 1255 return LargeMsgMaxUnicastMsgSize 1256 default: 1257 return DefaultMaxUnicastMsgSize 1258 } 1259 } 1260 1261 // unicastMaxMsgDuration returns the max duration to allow for a unicast send to complete 1262 func (n *Network) unicastMaxMsgDuration(messageType string) time.Duration { 1263 switch messageType { 1264 case "*messages.ChunkDataResponse", "messages.ChunkDataResponse": 1265 if LargeMsgUnicastTimeout > n.unicastMessageTimeout { 1266 return LargeMsgUnicastTimeout 1267 } 1268 return n.unicastMessageTimeout 1269 default: 1270 return n.unicastMessageTimeout 1271 } 1272 }