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 }