### Peer Scoring Setup Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Initializes and configures the peer scoring system. This allows the system to track and manage the reputation of connected peers. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub // Configure peer scoring parameters options := []pubsub.Option{ pubsub.WithPeerScore(pubsub.ScoreParams{ // Example parameters, tune these for your application // See go-libp2p-pubsub/peer_score.go for defaults and explanations Decay: pubsub.DecayDuration, // Default decay Downtime: pubsub.DowntimeWindow, // Default downtime window // ... other parameters ... }), pubsub.WithPeerScoreThresholds(pubsub.ScoreThresholds{ GossipThreshold: -100, PublishThreshold: -100, // ... other thresholds ... }), } // Apply the options to the PubSub instance (if not already done during initialization) // This example assumes ps is already created. In a real scenario, these options // would be passed to pubsub.NewGossipSub or similar constructor. // For demonstration, we'll simulate applying them. fmt.Println("Peer scoring configured.") // To access peer scores: // score, err := ps.GetPeerScore(peerId) // if err != nil { // log.Fatal(err) // } // fmt.Printf("Peer score: %d\n", score) } ``` -------------------------------- ### Message Validation Setup Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Configures and applies message validation rules. This is crucial for ensuring message integrity and security before processing. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub // Define a custom validator function myValidator := func(ctx context.Context, peerId peer.ID, msg *pubsub.Message) pubsub.ValidationResult { // Implement validation logic here // For example, check message size or content if len(msg.Data) > 1024 { return pubsub.Reject } return pubsub.Accept } // Set the validator for the PubSub instance ps.SetValidator(myValidator) // Messages will now be validated by myValidator before being delivered to subscribers. fmt.Println("Message validator set.") } ``` -------------------------------- ### Install go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/README.md Use this command to add the go-libp2p-pubsub package to your Go project. ```bash go get github.com/libp2p/go-libp2p-pubsub ``` -------------------------------- ### Basic Pub/Sub Usage Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Demonstrates fundamental publish and subscribe operations within the pub/sub system. This example serves as a starting point for understanding core messaging patterns. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere // ps, err := pubsub.NewGossipSub(ctx, mockHost, nil) // if err != nil { // log.Fatal(err) // } // Placeholder for a real PubSub instance var ps *pubsub.PubSub // Subscribe to a topic ssub, err := ps.Subscribe("my-topic") if err != nil { log.Fatal(err) } // Publish a message msg := []byte("Hello, PubSub!") if err := ps.Publish("my-topic", msg); err != nil { log.Fatal(err) } // Receive a message msg, err := ssub.Next(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Received message: %s from peer %s\n", string(msg.Data), msg.ReceivedFrom.String()) // Unsubscribe ssup := ssub.Cancel() if err := ssup; err != nil { log.Fatal(err) } } ``` -------------------------------- ### Configuration Options Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Illustrates how to apply various configuration options when initializing or modifying the PubSub system. This allows fine-tuning of behavior like message signing or logging. ```Go package main import ( "context" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Example of using configuration options during initialization // Assume mockHost is a libp2p host instance // ps, err := pubsub.NewGossipSub(ctx, mockHost, []pubsub.Option{ // pubsub.WithDirectConnect(), // Example option // pubsub.WithMaxMessageSize(1024 * 1024), // Example option // // ... other options ... // }) // if err != nil { // log.Fatal(err) // } // Placeholder for a real PubSub instance var ps *pubsub.PubSub // Applying options to an existing instance might require specific methods // or re-initialization depending on the option. fmt.Println("Configuration options applied (example shown during initialization).") } ``` -------------------------------- ### Event Tracking Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Demonstrates how to set up and use event handlers to track significant occurrences within the pub/sub system, such as peer joins or leaves. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub // Define an event handler function eventHandler := func(event pubsub.Event) { switch e := event.(type) { case pubsub.PeerJoinEvent: fmt.Printf("Peer joined: %s\n", e.Peer.String()) case pubsub.PeerLeaveEvent: fmt.Printf("Peer left: %s\n", e.Peer.String()) // Handle other event types as needed } } // Register the event handler ps.AddEventHandler(eventHandler) fmt.Println("Event handler registered.") // Events will now be dispatched to the registered handler. } ``` -------------------------------- ### Topic Operations Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Illustrates how to manage topics, including creating, joining, and leaving them. This is essential for organizing message streams. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub // Join a topic topic, err := ps.Join("another-topic") if err != nil { log.Fatal(err) } fmt.Printf("Joined topic: %s\n", topic.String()) // Leave a topic cancelled := topic.Close() if err := cancelled; err != nil { log.Fatal(err) } fmt.Printf("Left topic: %s\n", topic.String()) } ``` -------------------------------- ### Router Selection Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Shows how to select and configure different routing algorithms for the pub/sub system, such as Floodsub or GossipSub. This impacts message propagation efficiency and network topology. ```Go package main import ( "context" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume mockHost is a libp2p host instance // Example: Using GossipSub (default) // ps, err := pubsub.NewGossipSub(ctx, mockHost, nil) // if err != nil { // log.Fatal(err) // } // Example: Using Floodsub (if available as a separate implementation or option) // Note: go-libp2p-pubsub primarily uses GossipSub. Other routers might be // separate implementations or require specific configurations. // For demonstration, we assume a hypothetical NewFloodSub constructor. // ps, err := pubsub.NewFloodSub(ctx, mockHost, nil) // if err != nil { // log.Fatal(err) // } // Placeholder for a real PubSub instance var ps *pubsub.PubSub fmt.Println("Router selection demonstrated (GossipSub is common default).") } ``` -------------------------------- ### Subscription Patterns Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Shows various ways to handle subscriptions, including receiving messages, handling errors, and managing subscription lifecycle. Useful for building reliable message consumers. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub sub, err := ps.Subscribe("events") if err != nil { log.Fatal(err) } go func() { for { msg, err := sub.Next(ctx) if err != nil { if err == pubsub.ErrSubscriptionCancelled { fmt.Println("Subscription cancelled") return } log.Printf("Error receiving message: %v\n", err) continue } fmt.Printf("Received event: %s\n", string(msg.Data)) } }() // ... publish messages to "events" topic ... // To cancel the subscription: // cancelErr := sub.Cancel() // if cancelErr != nil { // log.Fatal(cancelErr) // } } ``` -------------------------------- ### Complete PubSub Configuration Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Demonstrates the full initialization of a GossipSub router with custom parameters, peer scoring, message signing, maximum message size, and logger. It also shows how to subscribe to a topic with buffer and message filtering, and register a topic validator. ```go package main import ( "context" "crypto/rand" "log/slog" "os" "time" "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" ) func main() { ctx := context.Background() // Create libp2p host host, _ := libp2p.New() defer host.Close() // Configure GossipSub parameters params := pubsub.DefaultGossipSubParams() params.D = 8 params.HeartbeatInterval = 500 * time.Millisecond // Configure peer scoring scoreParams := &pubsub.PeerScoreParams{ Topics: map[string]*pubsub.TopicScoreParams{ "my-topic": { TopicWeight: 1.0, TimeInMeshWeight: 1.0, TimeInMeshQuantum: time.Second, }, }, } scoreThresholds := &pubsub.PeerScoreThresholds{ GossipThreshold: -100, PublishThreshold: -200, GraylistThreshold: -300, } // Create PubSub with full configuration ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithGossipSubParams(params), pubsub.WithPeerScore(scoreParams, scoreThresholds), pubsub.WithMessageSigning(true), pubsub.WithMaxMessageSize(2 * 1024 * 1024), pubsub.WithLogger(slog.New(slog.NewJSONHandler(os.Stderr, nil))), ) // Subscribe with buffer configuration sub, _ := ps.Subscribe("my-topic", pubsub.WithBufferSize(256), pubsub.WithMessageFilter(func(msg *pubsub.Message) bool { return len(msg.Data) > 0 }), ) defer sub.Cancel() // Register validator ps.RegisterTopicValidator("my-topic", func(ctx context.Context, _ peer.ID, msg *pubsub.Message) pubsub.ValidationResult { if len(msg.Data) == 0 { return pubsub.ValidationReject } return pubsub.ValidationAccept }, pubsub.WithValidatorTimeout(5 * time.Second), ) // Use pubsub... } ``` -------------------------------- ### Conservative Initial Peer Score Parameters Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/peer-scoring.md Start with moderate peer score parameters and adjust based on observed behavior. This example sets conservative weights and decay rates for a production topic. ```go scoreParams := &pubsub.PeerScoreParams{ Topics: map[string]*pubsub.TopicScoreParams{ "production-topic": { TopicWeight: 1.0, TimeInMeshWeight: 0.5, // Conservative FirstMessageDeliveriesWeight: 1.0, MeshMessageDeliveriesWeight: -0.5, }, }, BehaviourPenaltyWeight: -5, // Light penalties initially DecayInterval: 12 * time.Second, DecayToZero: 0.01, } ``` -------------------------------- ### Message Batching Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Illustrates how to use message batching to send multiple messages efficiently in a single network transmission. This can improve throughput and reduce overhead. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub // Create a message batch batch := ps.NewMessageBatch() // Add messages to the batch msg1 := []byte("Batch message 1") msg2 := []byte("Batch message 2") batch.Add(msg1) batch.Add(msg2) // Publish the batch topic := "batch-topic" if err := ps.Publish(topic, batch.Bytes()); err != nil { log.Fatal(err) } fmt.Printf("Published batch of %d messages to topic %s\n", batch.Len(), topic) // Receiving and processing batched messages would involve parsing batch.Bytes() // and iterating through the individual messages. } ``` -------------------------------- ### Error Handling Example Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/COMPLETION_SUMMARY.txt Demonstrates how to catch and handle specific errors that can occur within the pub/sub system, such as subscription cancellations or topic closures. Proper error handling ensures robustness. ```Go package main import ( "context" "fmt" "log" "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Assume ps is a *pubsub.PubSub instance initialized elsewhere var ps *pubsub.PubSub sub, err := ps.Subscribe("error-topic") if err != nil { log.Fatal(err) } // Simulate cancelling the subscription externally go func() { // In a real scenario, this would happen based on some condition // time.Sleep(1 * time.Second) // cancelErr := sub.Cancel() // if cancelErr != nil { // log.Printf("Error during cancel: %v\n", cancelErr) // } }() // Attempt to receive a message, which will eventually error if cancelled _, err = sub.Next(ctx) if err != nil { if err == pubsub.ErrSubscriptionCancelled { fmt.Println("Caught expected error: Subscription cancelled.") } else { fmt.Printf("Caught unexpected error: %v\n", err) } } } ``` -------------------------------- ### Complete Peer Scoring Setup Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/peer-scoring.md Configures peer scoring parameters and thresholds for a pubsub instance. This includes topic-specific scoring, application-specific scores, and various penalty/reward factors. ```go func setupPeerScoring(ps *pubsub.PubSub) error { scoreParams := &pubsub.PeerScoreParams{ Topics: map[string]*pubsub.TopicScoreParams{ "consensus": { TopicWeight: 10.0, TimeInMeshWeight: 1.0, TimeInMeshQuantum: 1 * time.Second, TimeInMeshCap: 600, FirstMessageDeliveriesWeight: 5.0, FirstMessageDeliveriesDecay: 0.99, FirstMessageDeliveriesCap: 100, MeshMessageDeliveriesWeight: -10.0, MeshMessageDeliveriesThreshold: 20, MeshMessageDeliveriesWindow: 10 * time.Second, MeshMessageDeliveriesActivation: 5 * time.Second, MeshMessageDeliveriesDecay: 0.99, MeshFailurePenaltyWeight: -20.0, MeshFailurePenaltyDecay: 0.97, InvalidMessageDeliveriesWeight: -50.0, InvalidMessageDeliveriesDecay: 0.99, }, }, TopicScoreCap: 100.0, AppSpecificScore: func(p peer.ID) float64 { return 0.0 }, AppSpecificWeight: 1.0, IPColocationFactorWeight: -10.0, IPColocationFactorThreshold: 5, BehaviourPenaltyWeight: -10.0, BehaviourPenaltyThreshold: 3, BehaviourPenaltyDecay: 0.98, DecayInterval: 12 * time.Second, DecayToZero: 0.01, RetainScore: 10 * time.Minute, } scoreThresholds := &pubsub.PeerScoreThresholds{ GossipThreshold: -50, PublishThreshold: -100, GraylistThreshold: -500, AcceptPXThreshold: 20, OpportunisticGraftThreshold: 5, } return nil } ``` -------------------------------- ### Configure GossipSub Parameters Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Adjust GossipSub parameters for different network conditions like low-latency or high-throughput. Use `pubsub.DefaultGossipSubParams()` as a starting point. ```go params := pubsub.DefaultGossipSubParams() // For low-latency, small networks params.D = 8 params.HeartbeatInterval = 500 * time.Millisecond // For high-throughput networks params.HistoryLength = 10 params.MaxIHaveLength = 10000 // For high-latency networks params.HeartbeatInterval = 2 * time.Second params.IWantFollowupTime = 5 * time.Second ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithGossipSubParams(params)) ``` -------------------------------- ### Select PubSub Router Based on Network Size Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Dynamically choose between Floodsub, RandomSub, and GossipSub based on the estimated network size. This example demonstrates a common decision-making process. ```go if networkSize < 50 { ps, _ := pubsub.NewFloodSub(ctx, host) } else if networkSize < 500 { ps, _ := pubsub.NewRandomSub(ctx, host) } else { ps, _ := pubsub.NewGossipSub(ctx, host) } ``` -------------------------------- ### Get Default GossipSub Parameters Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Returns the default GossipSub parameter configuration. These parameters can be modified to tune the PubSub service's behavior. ```go func DefaultGossipSubParams() GossipSubParams ``` ```go params := pubsub.DefaultGossipSubParams() params.D = 8 // Increase mesh degree ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithGossipSubParams(params)) ``` -------------------------------- ### Implement Basic Validator Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/types.md An example implementation of a basic validator that checks if the message data length is within a valid range (greater than 0 and less than 1024 bytes). ```go validator := func(ctx context.Context, from peer.ID, msg *pubsub.Message) bool { return len(msg.Data) > 0 && len(msg.Data) < 1024 } ``` -------------------------------- ### Retrieve Topics from a Message Batch Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md Shows how to get a list of all topics currently present in a MessageBatch. This can be used to inspect the batch's contents before publishing. ```go batch := &pubsub.MessageBatch{} batch.Add("topic1", []byte("msg1")) batch.Add("topic2", []byte("msg2")) topics := batch.Topics() fmt.Printf("Topics in batch: %v\n", topics) // ["topic1", "topic2"] ``` -------------------------------- ### Handle NextPeerEvent with Context Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/event-handling.md Retrieves the next peer event (join or leave) using a context for cancellation or timeouts. This example demonstrates how to handle potential errors like context deadline exceeded or cancellation. ```go ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() evt, err := eventHandler.NextPeerEvent(ctx) if err != nil { if errors.Is(err, context.DeadlineExceeded) { fmt.Println("No events for 30 seconds") } return } switch evt.Type { case pubsub.PeerJoin: fmt.Printf("Peer joined: %s\n", evt.Peer) case pubsub.PeerLeave: fmt.Printf("Peer left: %s\n", evt.Peer) } ``` -------------------------------- ### Add messages to a batch via Topic handles Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md Messages can be added to a batch using Topic handles, which is beneficial when applying topic-specific options. This example joins two topics and adds messages to the batch. ```go batch := &pubsub.MessageBatch{} ctx := context.Background() topic1, _ := ps.Join("topic1") topic2, _ := ps.Join("topic2") topic1.AddToBatch(ctx, batch, []byte("message1")) topic2.AddToBatch(ctx, batch, []byte("message2")) err := ps.PublishBatch(batch) ``` -------------------------------- ### Implement Extended Validator Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/types.md An example implementation of an extended validator that rejects malformed messages, ignores pending ones, and accepts valid messages. This allows for more nuanced handling and peer penalization. ```go validatorEx := func(ctx context.Context, from peer.ID, msg *pubsub.Message) pubsub.ValidationResult { if !isWellFormed(msg.Data) { return pubsub.ValidationReject // Penalize peer } if isPending(msg) { return pubsub.ValidationIgnore // No penalty } return pubsub.ValidationAccept } ``` -------------------------------- ### Create GossipSub with Invalid Parameters Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/errors.md Shows an example of creating a GossipSub instance with invalid parameters, specifically when D (optimal degree) is greater than Dhi (upper bound for degree). This will result in a validation error. ```go params := pubsub.GossipSubParams{ D: 20, Dlo: 5, Dhi: 12, // Invalid: D > Dhi } ps, err := pubsub.NewGossipSub(ctx, host, pubsub.WithGossipSubParams(params)) ``` -------------------------------- ### Basic Publish and Subscribe Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md Demonstrates how to create a libp2p host, initialize a GossipSub router, subscribe to a topic, publish a message, and receive it. ```go package main import ( "context" "fmt" "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" ) func main() { ctx := context.Background() // Create libp2p host host, _ := libp2p.New() defer host.Close() // Create PubSub with GossipSub router ps, _ := pubsub.NewGossipSub(ctx, host) // Subscribe to topic sub, _ := ps.Subscribe("my-topic") defer sub.Cancel() // Publish a message ps.Publish("my-topic", []byte("Hello, pubsub!")) // Receive message msg, _ := sub.Next(ctx) fmt.Println(string(msg.Data)) } ``` -------------------------------- ### Get Default GossipSub Router Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Retrieves a GossipSubRouter configured with default parameters. ```go func DefaultGossipSubRouter(h host.Host) *GossipSubRouter ``` -------------------------------- ### Get Subscription Topic Name Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/subscription.md Retrieves the name of the pubsub topic to which the subscription is active. ```go sub, _ := ps.Subscribe("notifications") fmt.Printf("Subscribed to: %s\n", sub.Topic()) // Output: "notifications" ``` -------------------------------- ### Get Topic Name as String Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/topic.md Retrieves the name of the topic as a string. This is useful for debugging or logging purposes. ```go topic, _ := ps.Join("debug-info") fmt.Println(topic.String()) // Output: "debug-info" ``` -------------------------------- ### Subscription Methods Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Methods for interacting with subscriptions, including retrieving the next message, getting the topic name, and cancelling the subscription. ```APIDOC ## Subscription Methods ### Description Methods for interacting with subscriptions, including retrieving the next message, getting the topic name, and cancelling the subscription. ### Methods - `func (sub *Subscription) Next(ctx context.Context) (*Message, error)` - `func (sub *Subscription) Topic() string` - `func (sub *Subscription) Cancel() ``` -------------------------------- ### Testing Pub/Sub with Test Infrastructure Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md Utilize the `testutil` package to create a mesh of hosts and pub/sub instances for testing. Ensure to close all instances after testing using `defer testutil.CloseAll`. ```go import ( testutil "github.com/libp2p/go-libp2p-pubsub/test" ) // Create test mesh hosts, pubsubs := testutil.CreateMesh(ctx, 10, time.Minute) defer testutil.CloseAll(pubsubs) // Test your logic sub, _ := pubsubs[0].Subscribe("test-topic") pubsubs[1].Publish("test-topic", []byte("test")) ``` -------------------------------- ### Join and Manage a Topic Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md This snippet demonstrates joining a topic, publishing messages, subscribing to it, and setting up an event handler. Remember to close the topic and cancel handlers when done. ```go topic, _ := ps.Join("my-topic") defer topic.Close() // Publish topic.Publish(ctx, data) // Subscribe via topic sub, _ := topic.Subscribe() defer sub.Cancel() // Events handler, _ := topic.EventHandler() defer handler.Cancel() ``` -------------------------------- ### Import go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md Import the go-libp2p-pubsub library for use in your Go project. ```go import pubsub "github.com/libp2p/go-libp2p-pubsub" ``` -------------------------------- ### Get List of Subscribed Topics Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/pubsub.md Retrieve a list of all topic names the local peer is currently subscribed to. This is useful for understanding the current subscription status. ```go topics := ps.GetTopics() fmt.Printf("Subscribed to %d topics\n", len(topics)) for _, topic := range topics { fmt.Println(topic) } ``` -------------------------------- ### List project files in go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/README.md This tree structure outlines the organization of the go-libp2p-pubsub repository, detailing the location of different pubsub routers and core components. ```bash . ├── LICENSE ├── README.md # Regular Golang repo set up ├── codecov.yml ├── pb ├── go.mod ├── go.sum ├── doc.go # PubSub base ├── pubsub.go ├── blacklist.go ├── notify.go ├── comm.go ├── discovery.go ├── sign.go ├── subscription.go ├── topic.go ├── trace.go ├── tracer.go ├── validation.go # Floodsub router ├── floodsub.go # Randomsub router ├── randomsub.go # Gossipsub router ├── gossipsub.go ├── score.go ├── score_params.go └── mcache.go ``` -------------------------------- ### Enable Protobuf Tracing in go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/README.md Use this option to capture trace data in protobuf format. Ensure the provided path is valid for writing. ```go tracer, err := pubsub.NewPBTracer("/path/to/trace.pb") if err != nil { panic(err) } pubsub.NewGossipSub(..., pubsub.WithEventTracer(tracer)) ``` -------------------------------- ### Import and Basic Pub/Sub Operations Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/README.md Import the pubsub package and demonstrate the creation of a GossipSub instance, subscribing to a topic, publishing a message, and receiving a message. ```go import pubsub "github.com/libp2p/go-libp2p-pubsub" // Create instance with one of three routers ps, err := pubsub.NewGossipSub(ctx, host) // Subscribe to topic sub, err := ps.Subscribe("my-topic") // Publish message err := ps.Publish("my-topic", []byte("data")) // Receive message msg, err := sub.Next(ctx) ``` -------------------------------- ### Configure Topic Readiness Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Use WithReadiness to ensure a router is ready before publishing messages to a topic. ```go func WithReadiness(ready RouterReady) PubOpt ``` -------------------------------- ### go-libp2p-pubsub Package Structure Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Lists the main files and their purposes within the go-libp2p-pubsub package. ```go github.com/libp2p/go-libp2p-pubsub/ ├── pubsub.go # Main PubSub type ├── topic.go # Topic type ├── subscription.go # Subscription type ├── gossipsub.go # GossipSub router ├── floodsub.go # Floodsub router ├── randomsub.go # RandomSub router ├── validation.go # Validation pipeline ├── score.go # Peer scoring ├── score_params.go # Scoring parameters ├── tracer.go # Event tracing ├── blacklist.go # Peer blacklist ├── discovery.go # Discovery integration ├── messagebatch.go # Message batching └── ... (other files) ``` -------------------------------- ### Apply Message Filter to Subscription Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/subscription.md Configures a filter function to selectively accept or drop messages before they are added to the subscription's buffer. This example filters for messages with non-empty data. ```go sub, err := ps.Subscribe("filtered-topic", pubsub.WithMessageFilter(func(msg *pubsub.Message) bool { // Only accept messages from trusted sources return len(msg.Data) > 0 })) if err != nil { panic(err) } ``` -------------------------------- ### Enable JSON Tracing in go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/README.md Use this option to capture trace data as a JSON file. Ensure the provided path is valid for writing. ```go tracer, err := pubsub.NewJSONTracer("/path/to/trace.json") if err != nil { panic(err) } pubsub.NewGossipSub(..., pubsub.WithEventTracer(tracer)) ``` -------------------------------- ### Create RandomSub PubSub Instance Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/pubsub.md Use this to create a new PubSub instance with the RandomSub routing algorithm. RandomSub propagates messages to random subsets of peers. Requires a context, a libp2p Host instance, and optional configuration options. ```go func NewRandomSub(ctx context.Context, h host.Host, opts ...Option) (*PubSub, error) ``` -------------------------------- ### Track Peer Join/Leave Events Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md Shows how to set up an event handler to monitor when peers join or leave a specific topic. Ensure to cancel the event handler when done. ```go eventHandler, _ := topic.EventHandler() defer eventHandler.Cancel() for { evt, _ := eventHandler.NextPeerEvent(ctx) switch evt.Type { case pubsub.PeerJoin: fmt.Printf("Peer joined: %s\n", evt.Peer) case pubsub.PeerLeave: fmt.Printf("Peer left: %s\n", evt.Peer) } } ``` -------------------------------- ### Add Messages to a Batch and Publish Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md Demonstrates how to add multiple messages for different topics to a MessageBatch and then publish the entire batch using PublishBatch. This is useful for high-throughput scenarios. ```go batch := &pubsub.MessageBatch{} batch.Add("news-feed", []byte("Breaking news...")) batch.Add("alerts", []byte("System alert")) batch.Add("logs", []byte("Debug log entry")) err := ps.PublishBatch(batch) if err != nil { log.Printf("Batch publish failed: %v", err) } ``` -------------------------------- ### Configuration Options (With* functions) Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Various configuration options that can be passed to Pub/Sub creation and methods to customize behavior. ```APIDOC ## Configuration Options (With* functions) ### Description Various configuration options that can be passed to Pub/Sub creation and methods to customize behavior. ### Options #### Message Configuration - `WithMessageIdFn(fn MsgIdFunction) Option` - `WithMaxMessageSize(maxMessageSize int) Option` - `WithSeenMessagesTTL(ttl time.Duration) Option` - `WithSeenMessagesStrategy(strategy timecache.Strategy) Option` #### Signing - `WithMessageSigning(enabled bool) Option` - `WithMessageSignaturePolicy(policy MessageSignaturePolicy) Option` - `WithMessageAuthor(author peer.ID) Option` - `WithNoAuthor() Option` - `WithStrictSignatureVerification(required bool) Option` #### Peer Management - `WithPeerFilter(filter PeerFilter) Option` - `WithPeerOutboundQueueSize(size int) Option` - `WithBlacklist(b Blacklist) Option` #### Protocol - `WithProtocolMatchFn(m ProtocolMatchFn) Option` #### Logging and Tracing - `WithLogger(logger *slog.Logger) Option` - `WithRPCLogger(logger *slog.Logger) Option` - `WithEventTracer(tracer EventTracer) Option` - `WithRawTracer(tracer RawTracer) Option` #### Validation - `WithDefaultValidator(val interface{}, opts ...ValidatorOpt) Option` - `WithValidateQueueSize(n int) Option` - `WithValidateThrottle(n int) Option` - `WithValidateWorkers(n int) Option` #### Discovery - `WithDiscovery(d discovery.Discovery, opts ...DiscoverOpt) Option` #### GossipSub-Specific - `WithGossipSubParams(cfg GossipSubParams) Option` - `WithFloodPublish(floodPublish bool) Option` - `WithPeerExchange(doPX bool) Option` - `WithCustomPXRecordReducer(f PXRecordReducer) Option` - `OnlyPublicAddrsOnPeerExchange() Option` - `WithDirectPeers(pis []peer.AddrInfo) Option` - `WithDirectConnectTicks(t uint64) Option` - `WithGossipSubProtocols(protos []protocol.ID, feature GossipSubFeatureTest) Option` #### Scoring - `WithPeerScore(params *PeerScoreParams, thresholds *PeerScoreThresholds) Option` - `WithPeerGater(params *PeerGaterParams) Option` #### Other - `WithAppSpecificRpcInspector(inspector func(peer.ID, *RPC) error) Option` - `WithSubscriptionFilter(subFilter SubscriptionFilter) Option ``` -------------------------------- ### Create a RandomSub PubSub Instance Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Instantiates a PubSub service using the RandomSub protocol. This is suitable for bandwidth-constrained networks and simpler topologies. ```go func NewRandomSub(ctx context.Context, h host.Host, opts ...Option) (*PubSub, error) ``` -------------------------------- ### Create FloodSub PubSub Instance with Custom Protocols Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/pubsub.md Use this to create a PubSub instance using Floodsub with custom protocol IDs for multi-protocol negotiation. Requires a context, a libp2p Host instance, a slice of protocol IDs, and optional configuration options. ```go func NewFloodsubWithProtocols(ctx context.Context, h host.Host, ps []protocol.ID, opts ...Option) (*PubSub, error) ``` -------------------------------- ### Topic Validator Implementation Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/errors.md Register a custom topic validator function to control message acceptance, rejection, or ignoring based on message content and validation rules. This example shows how to handle different validation results. ```go ps.RegisterTopicValidator("strict-topic", func(ctx context.Context, from peer.ID, msg *pubsub.Message) pubsub.ValidationResult { // ValidationAccept - message is valid // ValidationReject - message is invalid, penalize peer // ValidationIgnore - message is invalid, but don't penalize if !wellFormed(msg.Data) { return pubsub.ValidationReject // Peer violated protocol } if isTemporarilyInvalid(msg.Data) { return pubsub.ValidationIgnore // No penalty } return pubsub.ValidationAccept }) ``` -------------------------------- ### Topic Options Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Functions to customize topic-level configurations for PubSub. ```go - WithReadiness(ready RouterReady) PubOpt - WithLocalPublication(local bool) PubOpt - WithValidatorData(data any) PubOpt - WithSecretKeyAndPeerId(key crypto.PrivKey, pid peer.ID) PubOpt ``` -------------------------------- ### Configure GossipSub with Common Options Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md Initialize a new GossipSub instance with various common configuration options. This includes message size, signing, peer management, logging, and validation settings. ```go ps, _ := pubsub.NewGossipSub(ctx, host, // Message configuration pubsub.WithMaxMessageSize(2*1024*1024), // 2MB max pubsub.WithMessageSigning(true), // Sign messages pubsub.WithSeenMessagesTTL(5*time.Minute), // Remember for 5 min // Peer management pubsub.WithPeerFilter(myPeerFilter), // Custom peer filter pubsub.WithBlacklist(myBlacklist), // Custom blacklist // Logging and tracing pubsub.WithLogger(logger), // Structured logging pubsub.WithEventTracer(tracer), // Event tracing // Validation pubsub.WithValidateThrottle(10000), // Max concurrent validations // GossipSub-specific pubsub.WithGossipSubParams(customParams), // Custom parameters pubsub.WithPeerScore(scoreParams, thresholds)) ``` -------------------------------- ### Configure Secret Key and Peer ID Signing Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Use WithSecretKeyAndPeerId to sign messages with a specific private key and peer ID. ```go func WithSecretKeyAndPeerId(key crypto.PrivKey, pid peer.ID) PubOpt ``` -------------------------------- ### Publish Batch with Error Handling Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md Shows how to publish a prepared message batch and handle potential errors during the publish operation, including suggestions for retry logic. ```go // Publish batch if err := ps.PublishBatch(batch); err != nil { log.Printf("Batch publish failed: %v", err) // Retry or handle error } ``` -------------------------------- ### Subscription Options Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Functions to customize subscription-level configurations for PubSub. ```go - WithBufferSize(size int) SubOpt - WithMessageFilter(filter func(*Message) bool) SubOpt ``` -------------------------------- ### Publish messages using a MessageBatch Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md This function demonstrates how to add multiple messages to a batch and then publish the entire batch using `ps.PublishBatch()`. Ensure `pubsub` is imported. ```go import ( "context" pubsub "github.com/libp2p/go-libp2p-pubsub" ) func publishBatch(ps *pubsub.PubSub, messages map[string][]byte) error { batch := &pubsub.MessageBatch{} for topic, data := range messages { batch.Add(topic, data) } return ps.PublishBatch(batch) } ``` -------------------------------- ### Enable Event Tracing for PubSub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Enables event tracing for detailed pubsub event recording. Use NewJSONTracer for file-based tracing. ```go jsonTracer, _ := pubsub.NewJSONTracer("/tmp/trace.json") ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithEventTracer(jsonTracer)) ``` -------------------------------- ### Create GossipSub PubSub Instance Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/pubsub.md Use this to create a new PubSub instance with the GossipSub routing algorithm. GossipSub implements mesh formation and gossip propagation for efficient message delivery. Requires a context, a libp2p Host instance, and optional configuration options. ```go import ( "context" "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" ) ctx := context.Background() host, _ := libp2p.New() ps, err := pubsub.NewGossipSub(ctx, host) if err != nil { panic(err) } ``` -------------------------------- ### Configure Local Publication Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Use WithLocalPublication to mark messages as locally published. ```go func WithLocalPublication(local bool) PubOpt ``` -------------------------------- ### Configure Peer Gating with WithPeerGater Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Use WithPeerGater to configure the behavior of peer gating. ```go pubsub.WithPeerGater(peerGaterParams) ``` -------------------------------- ### Enable Remote Tracing in go-libp2p-pubsub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/README.md Configure tracing to send data to a remote tracer. This requires the tracer to be running at the specified address and peer ID. ```go // assuming that your tracer runs in x.x.x.x and has a peer ID of QmTracer pi, err := peer.AddrInfoFromP2pAddr(ma.StringCast("/ip4/x.x.x.x/tcp/4001/p2p/QmTracer")) if err != nil { panic(err) } tracer, err := pubsub.NewRemoteTracer(ctx, host, pi) if err != nil { panic(err) } ps, err := pubsub.NewGossipSub(..., pubsub.WithEventTracer(tracer)) ``` -------------------------------- ### Create and Use TopicEventHandler Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/event-handling.md Creates a TopicEventHandler for a given topic and then enters a loop to process incoming peer join/leave events. It's important to cancel the handler when it's no longer needed to free up resources. ```go topic, _ := ps.Join("my-topic") eventHandler, err := topic.EventHandler() if err != nil { panic(err) } deffer eventHandler.Cancel() // Start receiving events for { evt, err := eventHandler.NextPeerEvent(ctx) if err != nil { break } fmt.Printf("Peer %s: %v\n", evt.Peer, evt.Type) } ``` -------------------------------- ### Benchmark Pub/Sub Batching Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/message-batch.md Compares the performance of single publishes versus batched publishes to measure the speedup achieved by batching. ```go func benchmarkBatching(ps *pubsub.PubSub, messageCount int) { // Single publishes start := time.Now() for i := 0; i < messageCount; i++ { ps.Publish(fmt.Sprintf("topic-%d", i%10), []byte("data")) } singleTime := time.Since(start) // Batched publishes start = time.Now() batch := &pubsub.MessageBatch{} for i := 0; i < messageCount; i++ { batch.Add(fmt.Sprintf("topic-%d", i%10), []byte("data")) } ps.PublishBatch(batch) batchTime := time.Since(start) fmt.Printf("Single: %v, Batch: %v, Speedup: %.1fx\n", singleTime, batchTime, float64(singleTime)/float64(batchTime)) } ``` -------------------------------- ### Configure GossipSub Protocols Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Use `WithGossipSubProtocols` to specify supported GossipSub protocol IDs for backward compatibility during negotiation. ```go ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithGossipSubProtocols( []protocol.ID{ pubsub.GossipSubID_v13, pubsub.GossipSubID_v12, pubsub.GossipSubID_v11, pubsub.FloodSubID, }, pubsub.GossipSubDefaultFeatures)) ``` -------------------------------- ### Subscribe to a Topic Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/OVERVIEW.md This snippet shows how to subscribe to a topic and process incoming messages. Ensure the context is managed and the subscription is cancelled upon completion. ```go sub, _ := ps.Subscribe("topic") defer sub.Cancel() for { msg, err := sub.Next(ctx) if err != nil { break } processMessage(msg) } ``` -------------------------------- ### Create a Topic Event Handler Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/topic.md Creates an event handler for tracking peer join/leave events on a topic. The handler should be cancelled when no longer needed. ```go topic, _ := ps.Join("peers-watch") evtHandler, err := topic.EventHandler() if err != nil { panic(err) } deferr evtHandler.Cancel() for { evt, err := evtHandler.NextPeerEvent(ctx) if err != nil { break } fmt.Printf("Peer %s: %v\n", evt.Peer, evt.Type) } ``` -------------------------------- ### Batch Publication Options Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/INDEX.md Options for customizing batch-level publication in PubSub. ```go (Batch-level publication customization) ``` -------------------------------- ### NewFloodSub Constructor Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/routers.md Creates a new PubSub instance using the Floodsub protocol. Requires a context and a libp2p Host instance. Configuration options can be provided. ```go func NewFloodSub(ctx context.Context, h host.Host, opts ...Option) (*PubSub, error) ``` ```go ps, err := pubsub.NewFloodSub(ctx, host) if err != nil { panic(err) } ``` -------------------------------- ### Basic Event Monitoring Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/event-handling.md Monitors peer join and leave events for a specific topic and prints messages indicating when peers join or leave. Requires joining a topic and obtaining an event handler. ```go import ( "context" "fmt" pubsub "github.com/libp2p/go-libp2p-pubsub" ) topic, _ := ps.Join("network-monitor") handler, _ := topic.EventHandler() defer handler.Cancel() for { evt, err := handler.NextPeerEvent(context.Background()) if err != nil { break } if evt.Type == pubsub.PeerJoin { fmt.Printf("New peer: %s\n", evt.Peer.String()[:8]) } else { fmt.Printf("Peer left: %s\n", evt.Peer.String()[:8]) } } ``` -------------------------------- ### Integrate Discovery Mechanism for PubSub Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/configuration.md Integrates a discovery mechanism for finding peers. Use WithDiscovery with a discovery.Discovery service and optional options. ```go // With IPFS DHT discovery dht, _ := dht.New(ctx, host) ps, _ := pubsub.NewGossipSub(ctx, host, pubsub.WithDiscovery(dht)) ``` -------------------------------- ### Join a Topic for Specific Operations Source: https://github.com/libp2p/go-libp2p-pubsub/blob/master/_autodocs/api-reference/pubsub.md Obtain a Topic handle to perform topic-specific actions like publishing or subscribing directly via the Topic interface. Remember to close the topic when done. ```go topic, err := ps.Join("my-topic") if err != nil { panic(err) } deffer topic.Close() // Publish via topic err = topic.Publish(ctx, []byte("hello")) if err != nil { panic(err) } // Subscribe via topic sub, err := topic.Subscribe() if err != nil { panic(err) } deffer sub.Cancel() ```