2019-07-02 12:40:25 +00:00
|
|
|
package lp2p
|
2019-07-01 09:09:48 +00:00
|
|
|
|
|
|
|
import (
|
2019-11-19 23:31:55 +00:00
|
|
|
"context"
|
2020-06-03 13:48:22 +00:00
|
|
|
"encoding/json"
|
2021-03-06 18:05:32 +00:00
|
|
|
"net"
|
2020-04-29 13:41:44 +00:00
|
|
|
"time"
|
2019-11-19 23:31:55 +00:00
|
|
|
|
2022-06-15 10:06:22 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2019-07-01 09:09:48 +00:00
|
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
2020-05-04 15:30:54 +00:00
|
|
|
pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb"
|
2022-06-15 10:06:22 +00:00
|
|
|
"github.com/minio/blake2b-simd"
|
2019-11-19 23:31:55 +00:00
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
2020-08-17 07:46:20 +00:00
|
|
|
"go.opencensus.io/stats"
|
2019-07-01 09:09:48 +00:00
|
|
|
"go.uber.org/fx"
|
2020-06-03 13:48:22 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-01 09:09:48 +00:00
|
|
|
|
2020-04-29 13:41:44 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2020-08-17 07:46:20 +00:00
|
|
|
"github.com/filecoin-project/lotus/metrics"
|
2020-05-04 15:30:54 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/config"
|
2020-04-29 13:41:44 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
2019-07-01 09:09:48 +00:00
|
|
|
)
|
|
|
|
|
2020-04-29 14:09:39 +00:00
|
|
|
func init() {
|
|
|
|
// configure larger overlay parameters
|
|
|
|
pubsub.GossipSubD = 8
|
|
|
|
pubsub.GossipSubDscore = 6
|
2020-06-03 21:03:31 +00:00
|
|
|
pubsub.GossipSubDout = 3
|
2020-04-29 14:09:39 +00:00
|
|
|
pubsub.GossipSubDlo = 6
|
|
|
|
pubsub.GossipSubDhi = 12
|
|
|
|
pubsub.GossipSubDlazy = 12
|
2020-05-04 15:30:54 +00:00
|
|
|
pubsub.GossipSubDirectConnectInitialDelay = 30 * time.Second
|
2020-08-20 15:08:02 +00:00
|
|
|
pubsub.GossipSubIWantFollowupTime = 5 * time.Second
|
2020-08-20 15:09:17 +00:00
|
|
|
pubsub.GossipSubHistoryLength = 10
|
2020-09-04 19:04:48 +00:00
|
|
|
pubsub.GossipSubGossipFactor = 0.1
|
2020-04-29 14:09:39 +00:00
|
|
|
}
|
2021-03-10 17:22:35 +00:00
|
|
|
|
|
|
|
const (
|
|
|
|
GossipScoreThreshold = -500
|
|
|
|
PublishScoreThreshold = -1000
|
|
|
|
GraylistScoreThreshold = -2500
|
|
|
|
AcceptPXScoreThreshold = 1000
|
|
|
|
OpportunisticGraftScoreThreshold = 3.5
|
|
|
|
)
|
|
|
|
|
2020-06-03 01:13:49 +00:00
|
|
|
func ScoreKeeper() *dtypes.ScoreKeeper {
|
|
|
|
return new(dtypes.ScoreKeeper)
|
|
|
|
}
|
|
|
|
|
2020-06-03 13:48:22 +00:00
|
|
|
type GossipIn struct {
|
|
|
|
fx.In
|
|
|
|
Mctx helpers.MetricsCtx
|
|
|
|
Lc fx.Lifecycle
|
|
|
|
Host host.Host
|
|
|
|
Nn dtypes.NetworkName
|
|
|
|
Bp dtypes.BootstrapPeers
|
2020-06-08 09:31:33 +00:00
|
|
|
Db dtypes.DrandBootstrap
|
2020-06-03 13:48:22 +00:00
|
|
|
Cfg *config.Pubsub
|
|
|
|
Sk *dtypes.ScoreKeeper
|
2020-09-09 18:37:12 +00:00
|
|
|
Dr dtypes.DrandSchedule
|
2020-06-03 13:48:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-23 19:56:03 +00:00
|
|
|
func getDrandTopic(chainInfoJSON string) (string, error) {
|
2020-06-03 13:48:22 +00:00
|
|
|
var drandInfo = struct {
|
|
|
|
Hash string `json:"hash"`
|
|
|
|
}{}
|
2020-06-23 19:56:03 +00:00
|
|
|
err := json.Unmarshal([]byte(chainInfoJSON), &drandInfo)
|
2020-06-03 13:48:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", xerrors.Errorf("could not unmarshal drand chain info: %w", err)
|
|
|
|
}
|
|
|
|
return "/drand/pubsub/v0.0.0/" + drandInfo.Hash, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
2020-05-14 01:10:49 +00:00
|
|
|
bootstrappers := make(map[peer.ID]struct{})
|
2020-06-03 13:48:22 +00:00
|
|
|
for _, pi := range in.Bp {
|
2020-05-14 01:10:49 +00:00
|
|
|
bootstrappers[pi.ID] = struct{}{}
|
|
|
|
}
|
2020-06-08 09:31:33 +00:00
|
|
|
drandBootstrappers := make(map[peer.ID]struct{})
|
|
|
|
for _, pi := range in.Db {
|
|
|
|
drandBootstrappers[pi.ID] = struct{}{}
|
|
|
|
}
|
|
|
|
|
2020-06-03 13:48:22 +00:00
|
|
|
isBootstrapNode := in.Cfg.Bootstrapper
|
2020-09-10 10:41:29 +00:00
|
|
|
|
|
|
|
drandTopicParams := &pubsub.TopicScoreParams{
|
|
|
|
// expected 2 beaconsn/min
|
|
|
|
TopicWeight: 0.5, // 5x block topic; max cap is 62.5
|
|
|
|
|
|
|
|
// 1 tick per second, maxes at 1 after 1 hour
|
|
|
|
TimeInMeshWeight: 0.00027, // ~1/3600
|
|
|
|
TimeInMeshQuantum: time.Second,
|
|
|
|
TimeInMeshCap: 1,
|
|
|
|
|
|
|
|
// deliveries decay after 1 hour, cap at 25 beacons
|
|
|
|
FirstMessageDeliveriesWeight: 5, // max value is 125
|
|
|
|
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
FirstMessageDeliveriesCap: 25, // the maximum expected in an hour is ~26, including the decay
|
|
|
|
|
|
|
|
// Mesh Delivery Failure is currently turned off for beacons
|
|
|
|
// This is on purpose as
|
|
|
|
// - the traffic is very low for meaningful distribution of incoming edges.
|
|
|
|
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
|
|
|
// so we might as well let opportunistic grafting repair the mesh on its own
|
|
|
|
// pace.
|
|
|
|
// - the network is too small, so large asymmetries can be expected between mesh
|
|
|
|
// edges.
|
|
|
|
// We should revisit this once the network grows.
|
|
|
|
|
|
|
|
// invalid messages decay after 1 hour
|
|
|
|
InvalidMessageDeliveriesWeight: -1000,
|
|
|
|
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
}
|
|
|
|
|
2022-02-10 17:21:21 +00:00
|
|
|
ingestTopicParams := &pubsub.TopicScoreParams{
|
|
|
|
// expected ~0.5 confirmed deals / min. sampled
|
2022-02-10 18:53:07 +00:00
|
|
|
TopicWeight: 0.1,
|
2022-02-10 17:21:21 +00:00
|
|
|
|
|
|
|
TimeInMeshWeight: 0.00027, // ~1/3600
|
|
|
|
TimeInMeshQuantum: time.Second,
|
|
|
|
TimeInMeshCap: 1,
|
|
|
|
|
2022-02-10 18:53:07 +00:00
|
|
|
FirstMessageDeliveriesWeight: 0.5,
|
2022-02-10 17:21:21 +00:00
|
|
|
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
FirstMessageDeliveriesCap: 100, // allowing for burstiness
|
|
|
|
|
|
|
|
InvalidMessageDeliveriesWeight: -1000,
|
|
|
|
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
}
|
|
|
|
|
2020-09-10 10:41:29 +00:00
|
|
|
topicParams := map[string]*pubsub.TopicScoreParams{
|
|
|
|
build.BlocksTopic(in.Nn): {
|
|
|
|
// expected 10 blocks/min
|
|
|
|
TopicWeight: 0.1, // max cap is 50, max mesh penalty is -10, single invalid message is -100
|
|
|
|
|
|
|
|
// 1 tick per second, maxes at 1 after 1 hour
|
|
|
|
TimeInMeshWeight: 0.00027, // ~1/3600
|
|
|
|
TimeInMeshQuantum: time.Second,
|
|
|
|
TimeInMeshCap: 1,
|
|
|
|
|
|
|
|
// deliveries decay after 1 hour, cap at 100 blocks
|
|
|
|
FirstMessageDeliveriesWeight: 5, // max value is 500
|
|
|
|
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
FirstMessageDeliveriesCap: 100, // 100 blocks in an hour
|
|
|
|
|
|
|
|
// Mesh Delivery Failure is currently turned off for blocks
|
|
|
|
// This is on purpose as
|
|
|
|
// - the traffic is very low for meaningful distribution of incoming edges.
|
|
|
|
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
|
|
|
// so we might as well let opportunistic grafting repair the mesh on its own
|
|
|
|
// pace.
|
|
|
|
// - the network is too small, so large asymmetries can be expected between mesh
|
|
|
|
// edges.
|
|
|
|
// We should revisit this once the network grows.
|
|
|
|
//
|
|
|
|
// // tracks deliveries in the last minute
|
|
|
|
// // penalty activates at 1 minute and expects ~0.4 blocks
|
|
|
|
// MeshMessageDeliveriesWeight: -576, // max penalty is -100
|
|
|
|
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
|
|
|
// MeshMessageDeliveriesCap: 10, // 10 blocks in a minute
|
|
|
|
// MeshMessageDeliveriesThreshold: 0.41666, // 10/12/2 blocks/min
|
|
|
|
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
|
|
|
// MeshMessageDeliveriesActivation: time.Minute,
|
|
|
|
//
|
|
|
|
// // decays after 15 min
|
|
|
|
// MeshFailurePenaltyWeight: -576,
|
|
|
|
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(15 * time.Minute),
|
|
|
|
|
|
|
|
// invalid messages decay after 1 hour
|
|
|
|
InvalidMessageDeliveriesWeight: -1000,
|
|
|
|
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
},
|
|
|
|
build.MessagesTopic(in.Nn): {
|
|
|
|
// expected > 1 tx/second
|
|
|
|
TopicWeight: 0.1, // max cap is 5, single invalid message is -100
|
|
|
|
|
|
|
|
// 1 tick per second, maxes at 1 hour
|
|
|
|
TimeInMeshWeight: 0.0002778, // ~1/3600
|
|
|
|
TimeInMeshQuantum: time.Second,
|
|
|
|
TimeInMeshCap: 1,
|
|
|
|
|
|
|
|
// deliveries decay after 10min, cap at 100 tx
|
|
|
|
FirstMessageDeliveriesWeight: 0.5, // max value is 50
|
|
|
|
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(10 * time.Minute),
|
|
|
|
FirstMessageDeliveriesCap: 100, // 100 messages in 10 minutes
|
|
|
|
|
|
|
|
// Mesh Delivery Failure is currently turned off for messages
|
|
|
|
// This is on purpose as the network is still too small, which results in
|
|
|
|
// asymmetries and potential unmeshing from negative scores.
|
|
|
|
// // tracks deliveries in the last minute
|
|
|
|
// // penalty activates at 1 min and expects 2.5 txs
|
|
|
|
// MeshMessageDeliveriesWeight: -16, // max penalty is -100
|
|
|
|
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
|
|
|
// MeshMessageDeliveriesCap: 100, // 100 txs in a minute
|
|
|
|
// MeshMessageDeliveriesThreshold: 2.5, // 60/12/2 txs/minute
|
|
|
|
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
|
|
|
// MeshMessageDeliveriesActivation: time.Minute,
|
|
|
|
|
|
|
|
// // decays after 5min
|
|
|
|
// MeshFailurePenaltyWeight: -16,
|
|
|
|
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(5 * time.Minute),
|
|
|
|
|
|
|
|
// invalid messages decay after 1 hour
|
|
|
|
InvalidMessageDeliveriesWeight: -1000,
|
|
|
|
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
pgTopicWeights := map[string]float64{
|
|
|
|
build.BlocksTopic(in.Nn): 10,
|
|
|
|
build.MessagesTopic(in.Nn): 1,
|
|
|
|
}
|
|
|
|
|
2020-10-08 18:48:55 +00:00
|
|
|
var drandTopics []string
|
2020-09-10 10:41:29 +00:00
|
|
|
for _, d := range in.Dr {
|
2020-10-08 18:48:55 +00:00
|
|
|
topic, err := getDrandTopic(d.Config.ChainInfoJSON)
|
2020-09-10 10:41:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-10-08 18:48:55 +00:00
|
|
|
topicParams[topic] = drandTopicParams
|
|
|
|
pgTopicWeights[topic] = 5
|
|
|
|
drandTopics = append(drandTopics, topic)
|
2020-06-03 13:48:22 +00:00
|
|
|
}
|
2020-05-14 01:10:49 +00:00
|
|
|
|
2022-02-10 17:21:21 +00:00
|
|
|
// Index ingestion whitelist
|
|
|
|
topicParams[build.IndexerIngestTopic(in.Nn)] = ingestTopicParams
|
|
|
|
|
2021-03-06 18:05:32 +00:00
|
|
|
// IP colocation whitelist
|
|
|
|
var ipcoloWhitelist []*net.IPNet
|
|
|
|
for _, cidr := range in.Cfg.IPColocationWhitelist {
|
|
|
|
_, ipnet, err := net.ParseCIDR(cidr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("error parsing IPColocation subnet %s: %w", cidr, err)
|
|
|
|
}
|
|
|
|
ipcoloWhitelist = append(ipcoloWhitelist, ipnet)
|
|
|
|
}
|
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
options := []pubsub.Option{
|
|
|
|
// Gossipsubv1.1 configuration
|
|
|
|
pubsub.WithFloodPublish(true),
|
2020-05-29 14:20:09 +00:00
|
|
|
pubsub.WithMessageIdFn(HashMsgId),
|
2020-05-14 01:10:49 +00:00
|
|
|
pubsub.WithPeerScore(
|
|
|
|
&pubsub.PeerScoreParams{
|
|
|
|
AppSpecificScore: func(p peer.ID) float64 {
|
|
|
|
// return a heavy positive score for bootstrappers so that we don't unilaterally prune
|
|
|
|
// them and accept PX from them.
|
|
|
|
// we don't do that in the bootstrappers themselves to avoid creating a closed mesh
|
|
|
|
// between them (however we might want to consider doing just that)
|
|
|
|
_, ok := bootstrappers[p]
|
|
|
|
if ok && !isBootstrapNode {
|
|
|
|
return 2500
|
|
|
|
}
|
|
|
|
|
2020-06-08 09:31:33 +00:00
|
|
|
_, ok = drandBootstrappers[p]
|
|
|
|
if ok && !isBootstrapNode {
|
|
|
|
return 1500
|
|
|
|
}
|
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
// TODO: we want to plug the application specific score to the node itself in order
|
|
|
|
// to provide feedback to the pubsub system based on observed behaviour
|
|
|
|
return 0
|
|
|
|
},
|
|
|
|
AppSpecificWeight: 1,
|
|
|
|
|
2020-10-06 06:11:44 +00:00
|
|
|
// This sets the IP colocation threshold to 5 peers before we apply penalties
|
|
|
|
IPColocationFactorThreshold: 5,
|
2020-05-14 01:10:49 +00:00
|
|
|
IPColocationFactorWeight: -100,
|
2021-03-06 18:05:32 +00:00
|
|
|
IPColocationFactorWhitelist: ipcoloWhitelist,
|
2020-05-14 01:10:49 +00:00
|
|
|
|
2020-05-12 16:21:11 +00:00
|
|
|
// P7: behavioural penalties, decay after 1hr
|
2020-08-20 19:32:41 +00:00
|
|
|
BehaviourPenaltyThreshold: 6,
|
2020-08-20 15:08:02 +00:00
|
|
|
BehaviourPenaltyWeight: -10,
|
|
|
|
BehaviourPenaltyDecay: pubsub.ScoreParameterDecay(time.Hour),
|
2020-05-12 16:21:11 +00:00
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
DecayInterval: pubsub.DefaultDecayInterval,
|
|
|
|
DecayToZero: pubsub.DefaultDecayToZero,
|
|
|
|
|
|
|
|
// this retains non-positive scores for 6 hours
|
|
|
|
RetainScore: 6 * time.Hour,
|
|
|
|
|
|
|
|
// topic parameters
|
2020-09-10 10:41:29 +00:00
|
|
|
Topics: topicParams,
|
2020-05-14 01:10:49 +00:00
|
|
|
},
|
|
|
|
&pubsub.PeerScoreThresholds{
|
2021-03-10 17:22:35 +00:00
|
|
|
GossipThreshold: GossipScoreThreshold,
|
|
|
|
PublishThreshold: PublishScoreThreshold,
|
|
|
|
GraylistThreshold: GraylistScoreThreshold,
|
|
|
|
AcceptPXThreshold: AcceptPXScoreThreshold,
|
|
|
|
OpportunisticGraftThreshold: OpportunisticGraftScoreThreshold,
|
2020-05-14 01:10:49 +00:00
|
|
|
},
|
|
|
|
),
|
2020-06-03 13:48:22 +00:00
|
|
|
pubsub.WithPeerScoreInspect(in.Sk.Update, 10*time.Second),
|
2020-05-14 01:10:49 +00:00
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
// enable Peer eXchange on bootstrappers
|
|
|
|
if isBootstrapNode {
|
|
|
|
// turn off the mesh in bootstrappers -- only do gossip and PX
|
|
|
|
pubsub.GossipSubD = 0
|
|
|
|
pubsub.GossipSubDscore = 0
|
|
|
|
pubsub.GossipSubDlo = 0
|
|
|
|
pubsub.GossipSubDhi = 0
|
2020-05-21 09:11:22 +00:00
|
|
|
pubsub.GossipSubDout = 0
|
2020-09-04 19:04:48 +00:00
|
|
|
pubsub.GossipSubDlazy = 64
|
|
|
|
pubsub.GossipSubGossipFactor = 0.25
|
2020-08-27 18:12:38 +00:00
|
|
|
pubsub.GossipSubPruneBackoff = 5 * time.Minute
|
2020-05-14 01:10:49 +00:00
|
|
|
// turn on PX
|
|
|
|
options = append(options, pubsub.WithPeerExchange(true))
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
// direct peers
|
2020-06-03 13:48:22 +00:00
|
|
|
if in.Cfg.DirectPeers != nil {
|
2020-05-14 01:10:49 +00:00
|
|
|
var directPeerInfo []peer.AddrInfo
|
2020-05-04 15:30:54 +00:00
|
|
|
|
2020-06-03 13:48:22 +00:00
|
|
|
for _, addr := range in.Cfg.DirectPeers {
|
2020-05-14 01:10:49 +00:00
|
|
|
a, err := ma.NewMultiaddr(addr)
|
2020-05-04 15:30:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
pi, err := peer.AddrInfoFromP2pAddr(a)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
directPeerInfo = append(directPeerInfo, *pi)
|
|
|
|
}
|
|
|
|
|
|
|
|
options = append(options, pubsub.WithDirectPeers(directPeerInfo))
|
|
|
|
}
|
|
|
|
|
2020-09-03 12:33:29 +00:00
|
|
|
// validation queue RED
|
2020-09-07 16:54:38 +00:00
|
|
|
var pgParams *pubsub.PeerGaterParams
|
|
|
|
|
|
|
|
if isBootstrapNode {
|
|
|
|
pgParams = pubsub.NewPeerGaterParams(
|
|
|
|
0.33,
|
|
|
|
pubsub.ScoreParameterDecay(2*time.Minute),
|
|
|
|
pubsub.ScoreParameterDecay(10*time.Minute),
|
|
|
|
).WithTopicDeliveryWeights(pgTopicWeights)
|
|
|
|
} else {
|
|
|
|
pgParams = pubsub.NewPeerGaterParams(
|
|
|
|
0.33,
|
|
|
|
pubsub.ScoreParameterDecay(2*time.Minute),
|
|
|
|
pubsub.ScoreParameterDecay(time.Hour),
|
|
|
|
).WithTopicDeliveryWeights(pgTopicWeights)
|
|
|
|
}
|
|
|
|
|
|
|
|
options = append(options, pubsub.WithPeerGater(pgParams))
|
2020-10-08 18:48:55 +00:00
|
|
|
|
|
|
|
allowTopics := []string{
|
|
|
|
build.BlocksTopic(in.Nn),
|
|
|
|
build.MessagesTopic(in.Nn),
|
2022-02-04 08:15:01 +00:00
|
|
|
build.IndexerIngestTopic(in.Nn),
|
2020-10-08 18:48:55 +00:00
|
|
|
}
|
|
|
|
allowTopics = append(allowTopics, drandTopics...)
|
2020-10-08 18:40:36 +00:00
|
|
|
options = append(options,
|
|
|
|
pubsub.WithSubscriptionFilter(
|
|
|
|
pubsub.WrapLimitSubscriptionFilter(
|
2020-10-08 18:48:55 +00:00
|
|
|
pubsub.NewAllowlistSubscriptionFilter(allowTopics...),
|
2020-10-08 18:40:36 +00:00
|
|
|
100)))
|
2020-09-03 12:33:29 +00:00
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
// tracer
|
2020-06-03 13:48:22 +00:00
|
|
|
if in.Cfg.RemoteTracer != "" {
|
|
|
|
a, err := ma.NewMultiaddr(in.Cfg.RemoteTracer)
|
2020-05-14 01:10:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
pi, err := peer.AddrInfoFromP2pAddr(a)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-04-29 14:03:41 +00:00
|
|
|
}
|
2020-04-29 13:41:44 +00:00
|
|
|
|
2020-06-03 13:48:22 +00:00
|
|
|
tr, err := pubsub.NewRemoteTracer(context.TODO(), in.Host, *pi)
|
2020-05-14 01:10:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-04-29 13:41:44 +00:00
|
|
|
|
2020-07-31 07:15:21 +00:00
|
|
|
trw := newTracerWrapper(tr, build.BlocksTopic(in.Nn))
|
2020-05-14 01:10:49 +00:00
|
|
|
options = append(options, pubsub.WithEventTracer(trw))
|
2020-08-17 07:46:20 +00:00
|
|
|
} else {
|
|
|
|
// still instantiate a tracer for collecting metrics
|
|
|
|
trw := newTracerWrapper(nil)
|
|
|
|
options = append(options, pubsub.WithEventTracer(trw))
|
2019-07-01 09:09:48 +00:00
|
|
|
}
|
2020-05-14 01:10:49 +00:00
|
|
|
|
2020-06-03 13:48:22 +00:00
|
|
|
return pubsub.NewGossipSub(helpers.LifecycleCtx(in.Mctx, in.Lc), in.Host, options...)
|
2019-07-01 09:09:48 +00:00
|
|
|
}
|
|
|
|
|
2020-05-04 16:34:30 +00:00
|
|
|
func HashMsgId(m *pubsub_pb.Message) string {
|
|
|
|
hash := blake2b.Sum256(m.Data)
|
|
|
|
return string(hash[:])
|
|
|
|
}
|
|
|
|
|
2020-07-31 07:15:21 +00:00
|
|
|
func newTracerWrapper(tr pubsub.EventTracer, topics ...string) pubsub.EventTracer {
|
2020-08-17 07:46:20 +00:00
|
|
|
var topicsMap map[string]struct{}
|
|
|
|
if len(topics) > 0 {
|
|
|
|
topicsMap = make(map[string]struct{})
|
|
|
|
for _, topic := range topics {
|
|
|
|
topicsMap[topic] = struct{}{}
|
|
|
|
}
|
2020-07-31 07:15:21 +00:00
|
|
|
}
|
2020-08-17 07:46:20 +00:00
|
|
|
|
2020-07-31 07:15:21 +00:00
|
|
|
return &tracerWrapper{tr: tr, topics: topicsMap}
|
2020-05-04 15:30:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type tracerWrapper struct {
|
2020-07-31 07:15:21 +00:00
|
|
|
tr pubsub.EventTracer
|
|
|
|
topics map[string]struct{}
|
|
|
|
}
|
|
|
|
|
2020-10-08 18:40:36 +00:00
|
|
|
func (trw *tracerWrapper) traceMessage(topic string) bool {
|
|
|
|
_, ok := trw.topics[topic]
|
|
|
|
return ok
|
2020-05-04 15:30:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (trw *tracerWrapper) Trace(evt *pubsub_pb.TraceEvent) {
|
|
|
|
// this filters the trace events reported to the remote tracer to include only
|
|
|
|
// JOIN/LEAVE/GRAFT/PRUNE/PUBLISH/DELIVER. This significantly reduces bandwidth usage and still
|
|
|
|
// collects enough data to recover the state of the mesh and compute message delivery latency
|
|
|
|
// distributions.
|
2020-07-31 07:15:21 +00:00
|
|
|
// Furthermore, we only trace message publication and deliveries for specified topics
|
|
|
|
// (here just the blocks topic).
|
2020-05-04 15:30:54 +00:00
|
|
|
switch evt.GetType() {
|
|
|
|
case pubsub_pb.TraceEvent_PUBLISH_MESSAGE:
|
2020-08-17 07:46:20 +00:00
|
|
|
stats.Record(context.TODO(), metrics.PubsubPublishMessage.M(1))
|
2020-10-08 18:40:36 +00:00
|
|
|
if trw.tr != nil && trw.traceMessage(evt.GetPublishMessage().GetTopic()) {
|
2020-07-31 07:15:21 +00:00
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
case pubsub_pb.TraceEvent_DELIVER_MESSAGE:
|
2020-08-17 07:46:20 +00:00
|
|
|
stats.Record(context.TODO(), metrics.PubsubDeliverMessage.M(1))
|
2020-10-08 18:40:36 +00:00
|
|
|
if trw.tr != nil && trw.traceMessage(evt.GetDeliverMessage().GetTopic()) {
|
2020-07-31 07:15:21 +00:00
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-08-17 07:46:20 +00:00
|
|
|
case pubsub_pb.TraceEvent_REJECT_MESSAGE:
|
|
|
|
stats.Record(context.TODO(), metrics.PubsubRejectMessage.M(1))
|
|
|
|
case pubsub_pb.TraceEvent_DUPLICATE_MESSAGE:
|
|
|
|
stats.Record(context.TODO(), metrics.PubsubDuplicateMessage.M(1))
|
2020-05-04 15:30:54 +00:00
|
|
|
case pubsub_pb.TraceEvent_JOIN:
|
2020-08-17 07:46:20 +00:00
|
|
|
if trw.tr != nil {
|
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
case pubsub_pb.TraceEvent_LEAVE:
|
2020-08-17 07:46:20 +00:00
|
|
|
if trw.tr != nil {
|
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
case pubsub_pb.TraceEvent_GRAFT:
|
2020-08-17 07:46:20 +00:00
|
|
|
if trw.tr != nil {
|
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-05-04 15:30:54 +00:00
|
|
|
case pubsub_pb.TraceEvent_PRUNE:
|
2020-08-17 07:46:20 +00:00
|
|
|
if trw.tr != nil {
|
|
|
|
trw.tr.Trace(evt)
|
|
|
|
}
|
2020-08-20 20:14:32 +00:00
|
|
|
case pubsub_pb.TraceEvent_RECV_RPC:
|
|
|
|
stats.Record(context.TODO(), metrics.PubsubRecvRPC.M(1))
|
|
|
|
case pubsub_pb.TraceEvent_SEND_RPC:
|
|
|
|
stats.Record(context.TODO(), metrics.PubsubSendRPC.M(1))
|
|
|
|
case pubsub_pb.TraceEvent_DROP_RPC:
|
|
|
|
stats.Record(context.TODO(), metrics.PubsubDropRPC.M(1))
|
2019-07-01 09:09:48 +00:00
|
|
|
}
|
|
|
|
}
|