github.com/amazechain/amc@v0.1.3/internal/p2p/pubsub_filter.go (about)

     1  package p2p
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/amazechain/amc/internal/p2p/encoder"
     6  	"strings"
     7  
     8  	pubsub "github.com/libp2p/go-libp2p-pubsub"
     9  	pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
    10  	"github.com/libp2p/go-libp2p/core/peer"
    11  )
    12  
    13  // It is set at this limit to handle the possibility
    14  // of double topic subscriptions at fork boundaries.
    15  // -> 64 Attestation Subnets * 2.
    16  // -> 4 Sync Committee Subnets * 2.
    17  // -> Block,Aggregate,ProposerSlashing,AttesterSlashing,Exits,SyncContribution * 2.
    18  const pubsubSubscriptionRequestLimit = 200
    19  
    20  // CanSubscribe returns true if the topic is of interest and we could subscribe to it.
    21  func (s *Service) CanSubscribe(topic string) bool {
    22  	parts := strings.Split(topic, "/")
    23  	if len(parts) != 5 {
    24  		return false
    25  	}
    26  	// The topic must start with a slash, which means the first part will be empty.
    27  	if parts[0] != "" {
    28  		return false
    29  	}
    30  	if parts[1] != "amc" {
    31  		return false
    32  	}
    33  
    34  	//fork
    35  	if parts[4] != encoder.ProtocolSuffixSSZSnappy {
    36  		return false
    37  	}
    38  
    39  	// Check the incoming topic matches any topic mapping. This includes a check for part[3].
    40  	for gt := range gossipTopicMappings {
    41  		if _, err := scanfcheck(strings.Join(parts[0:4], "/"), gt); err == nil {
    42  			return true
    43  		}
    44  	}
    45  
    46  	return false
    47  }
    48  
    49  // FilterIncomingSubscriptions is invoked for all RPCs containing subscription notifications.
    50  // This method returns only the topics of interest and may return an error if the subscription
    51  // request contains too many topics.
    52  func (s *Service) FilterIncomingSubscriptions(_ peer.ID, subs []*pubsubpb.RPC_SubOpts) ([]*pubsubpb.RPC_SubOpts, error) {
    53  	if len(subs) > pubsubSubscriptionRequestLimit {
    54  		return nil, pubsub.ErrTooManySubscriptions
    55  	}
    56  
    57  	return pubsub.FilterSubscriptions(subs, s.CanSubscribe), nil
    58  }
    59  
    60  // scanfcheck uses fmt.Sscanf to check that a given string matches expected format. This method
    61  // returns the number of formatting substitutions matched and error if the string does not match
    62  // the expected format. Note: this method only accepts integer compatible formatting substitutions
    63  // such as %d or %x.
    64  func scanfcheck(input, format string) (int, error) {
    65  	var t int
    66  	// Sscanf requires argument pointers with the appropriate type to load the value from the input.
    67  	// This method only checks that the input conforms to the format, the arguments are not used and
    68  	// therefore we can reuse the same integer pointer.
    69  	var cnt = strings.Count(format, "%")
    70  	var args []interface{}
    71  	for i := 0; i < cnt; i++ {
    72  		args = append(args, &t)
    73  	}
    74  	return fmt.Sscanf(input, format, args...)
    75  }