github.com/ava-labs/avalanchego@v1.11.11/network/p2p/gossip/handler.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package gossip
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	"go.uber.org/zap"
    11  
    12  	"github.com/ava-labs/avalanchego/ids"
    13  	"github.com/ava-labs/avalanchego/network/p2p"
    14  	"github.com/ava-labs/avalanchego/snow/engine/common"
    15  	"github.com/ava-labs/avalanchego/utils/bloom"
    16  	"github.com/ava-labs/avalanchego/utils/logging"
    17  )
    18  
    19  var _ p2p.Handler = (*Handler[*testTx])(nil)
    20  
    21  func NewHandler[T Gossipable](
    22  	log logging.Logger,
    23  	marshaller Marshaller[T],
    24  	set Set[T],
    25  	metrics Metrics,
    26  	targetResponseSize int,
    27  ) *Handler[T] {
    28  	return &Handler[T]{
    29  		Handler:            p2p.NoOpHandler{},
    30  		log:                log,
    31  		marshaller:         marshaller,
    32  		set:                set,
    33  		metrics:            metrics,
    34  		targetResponseSize: targetResponseSize,
    35  	}
    36  }
    37  
    38  type Handler[T Gossipable] struct {
    39  	p2p.Handler
    40  	marshaller         Marshaller[T]
    41  	log                logging.Logger
    42  	set                Set[T]
    43  	metrics            Metrics
    44  	targetResponseSize int
    45  }
    46  
    47  func (h Handler[T]) AppRequest(_ context.Context, _ ids.NodeID, _ time.Time, requestBytes []byte) ([]byte, *common.AppError) {
    48  	filter, salt, err := ParseAppRequest(requestBytes)
    49  	if err != nil {
    50  		return nil, p2p.ErrUnexpected
    51  	}
    52  
    53  	responseSize := 0
    54  	gossipBytes := make([][]byte, 0)
    55  	h.set.Iterate(func(gossipable T) bool {
    56  		gossipID := gossipable.GossipID()
    57  
    58  		// filter out what the requesting peer already knows about
    59  		if bloom.Contains(filter, gossipID[:], salt[:]) {
    60  			return true
    61  		}
    62  
    63  		var bytes []byte
    64  		bytes, err = h.marshaller.MarshalGossip(gossipable)
    65  		if err != nil {
    66  			return false
    67  		}
    68  
    69  		// check that this doesn't exceed our maximum configured target response
    70  		// size
    71  		gossipBytes = append(gossipBytes, bytes)
    72  		responseSize += len(bytes)
    73  
    74  		return responseSize <= h.targetResponseSize
    75  	})
    76  	if err != nil {
    77  		return nil, p2p.ErrUnexpected
    78  	}
    79  
    80  	if err := h.metrics.observeMessage(sentPullLabels, len(gossipBytes), responseSize); err != nil {
    81  		return nil, p2p.ErrUnexpected
    82  	}
    83  
    84  	response, err := MarshalAppResponse(gossipBytes)
    85  	if err != nil {
    86  		return nil, p2p.ErrUnexpected
    87  	}
    88  
    89  	return response, nil
    90  }
    91  
    92  func (h Handler[_]) AppGossip(_ context.Context, nodeID ids.NodeID, gossipBytes []byte) {
    93  	gossip, err := ParseAppGossip(gossipBytes)
    94  	if err != nil {
    95  		h.log.Debug("failed to unmarshal gossip", zap.Error(err))
    96  		return
    97  	}
    98  
    99  	receivedBytes := 0
   100  	for _, bytes := range gossip {
   101  		receivedBytes += len(bytes)
   102  		gossipable, err := h.marshaller.UnmarshalGossip(bytes)
   103  		if err != nil {
   104  			h.log.Debug("failed to unmarshal gossip",
   105  				zap.Stringer("nodeID", nodeID),
   106  				zap.Error(err),
   107  			)
   108  			continue
   109  		}
   110  
   111  		if err := h.set.Add(gossipable); err != nil {
   112  			h.log.Debug(
   113  				"failed to add gossip to the known set",
   114  				zap.Stringer("nodeID", nodeID),
   115  				zap.Stringer("id", gossipable.GossipID()),
   116  				zap.Error(err),
   117  			)
   118  		}
   119  	}
   120  
   121  	if err := h.metrics.observeMessage(receivedPushLabels, len(gossip), receivedBytes); err != nil {
   122  		h.log.Error("failed to update metrics",
   123  			zap.Error(err),
   124  		)
   125  	}
   126  }