Skip to content

Generalised Gossipsub #664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

AgeManning
Copy link
Contributor

Overview

This an idea for modularizing gossipsub to allow for greater optimizations while minimizing any engineering effort for implementations that current support gossipsub.

Fundamentally this is just a re-factor of code, with the addition of two new control messages:
CHOKE/UNCHOKE

The added control messages are the only thing that needs to be implemented to support this change. Any variation of these control messages would also work, I think we just need this degree of freedom to adjust mesh broadcasts without having to adjust the mesh sizes.

tldr

We shift current gossipsub logic into conceptual modules called strategies:

  • Broadcast strategy - Controls how we send messages, can tune amount of gossip vs direct message sending
  • Mesh strategy - Controls how we form networks. How big is the mesh, who we want to connect to, how it changes over time
  • Scoring - Different scoring algorithms.

Each of these can be applied per-topic (and dynamically if needed), allowing a complex network with competing constraints to choose different strategies per different applications (per-topic) or under different scenarios (i.e bandwidth limitations).

Benefits (Intended at least)

  • Researches/Developers can fine-tune networks without having to modify the spec (they do this via stating/specing new strategies)
  • Strategies can be applied dynamically and per topic, allowing a greater configuration space for complex use cases
  • Implementations can mix/match or change dynamically if the network scenario changes, giving more flexibility to handle changing network conditions
  • I'm hoping testing becomes easier. Researches can add/replace strategies and test them against a baseline a bit more easily.

@vyzo
Copy link
Contributor

vyzo commented Mar 17, 2025

Just a small structural comment, can we put those under pubsub/ at the very least?

Ideally it should go into the pubsub/gossipsub/ ditectory

@AgeManning
Copy link
Contributor Author

Yeah sure. This is still very much a rough draft. Can move location and fix a lot of this up, if there is any interest in this

Copy link
Contributor

@MarcoPolo MarcoPolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done an initial pass on these documents. Thank you for writing this! I like the general idea and want to clarify a couple high level points before diving into some of the details.



  1. How can new strategies be sure to be compatible with other strategies and their scoring methods?
    1. Specifically, how can new strategies stay backwards compatible with the expectations of the existing gossipsub network?
    2. Generally, I wonder if we need to define rules of what peers MUST NOT do in order to remain in good standing.
    3. This might be the trickiest part of this proposal.
  2. Do we need a way to add new messages to the protocol?
    1. It seems to me that Choke is needed here for the "random choke" strategy. I can imagine new strategies which needing new messages as well.
      1. example: A variant on choke that allows for new original messages to be sent, while still avoiding forwarded messages.
    2. My concern is overfitting for these two strategies while claiming a generic interface.
      1. Maybe drafting a third strategy would be enough to address this concern.
  3. Is the expectation that within a given topic different peers may implement different strategies depending on their own concerns?

@vyzo
Copy link
Contributor

vyzo commented Mar 18, 2025

CHOKE is also needed for implementing the announcesub proposal, where we then use eager IHAVE instead of IANNOUNCE.

@AgeManning
Copy link
Contributor Author

@MarcoPolo Thanks for the comments.

  1. From a pure interop perspective, as long as they are sending the spec'd messages, any strategy is "compatible" with any other. This is entirely backwards compatible. Implementations that don't have choke/unchoke, we just don't send them these messages. If we just use the original gossipsub strategy, there is no difference.

However, I think you're asking more or less how the general network would look, and whether different scoring strategies can work together. In general they can't. I imagine, this to be spec'd outside of libp2p. For example, if Ethereum wanted to use a specific strategy, they would would specify that so that all of their nodes used one strategy. There is no versioning, you are right. Perhaps that might be something to add, but in the Ethereum case, we can upgrade strategies on hard forks to avoid partial upgrades.
ii. The problem as I see it, is that gossipsub attempts to be too general. What I mean by this, is that its a protocol thats used by many implementations and many networks. If someone wants to make a modification, it cannot be just that its good for one application, but it must be good for every single application on every network that uses gossipsub. Therefore in the Ethereum case, we can't engineer something that works just for Ethereum and put it into the specs, if it doesn't work for everyone else. So the definition of what peers must do to be in good standing, I think each network/application should define themselves outside of the gossipsub spec.

  1. No, we don't. The reason for adding it, seems to be that attempts at optimizing current gossipsub involve changing how the mesh works. It adds an extra degree of freedom to do this. I added it, because I think it solves two proposed solutions to improve gossipsub (Gossipsub v2.0 spec: Lower or zero duplicates by lazy mesh propagation #653) (the thing I called random choke) and "episub" (Gossipsub extension for Epidemic Meshes (v1.2.0) #413). It adds a degree of freedom to do what people are suggesting by modifying the mesh. I agree with you, it could be over-fitting, but I've not seen other proposals to improve gossipsub that require other messages. In either case, I think adding new protocol messages, would be simpler in this case. We define what they do, how to handle them in the spec, then whatever strategy can contain the more complex logic and implementations that require it can implement the strategy or not.

  2. The idea is to shift the burden of this decision to outside the libp2p specs, so every use case can decide for itself. Some applications may have static strategies for all topics (as is now), but if people want to shift and change them and experiment, they are able to, without having to make a spec change and enforce it on everyone else. Also, if it decided that it doesn't work in practice, it can be easily reverted.

Comment on lines +300 to +304
When a message is received that is valid and was not published by the router itself, the router informs the broadcast module via the
Forward(Topic) interface.

The broadcast module will return which peers to forward the message to and which
to gossip to (if any).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems contradicting to what is said earlier in this file.

Upon receiving a `CHOKE` message, the router MUST no longer forward messages to
the peer that sent the `CHOKE` message, while it is still in the mesh. Instead
it MUST always send an IHAVE message (provided there are messages to send and
it does not hit the IHAVE message limit) immediately to the peer.

It's already stated in this file that you must send IHAVE instead of forwarding the message to peers that sent the CHOKE message.

How can the broadcast module do otherwise? If it can't, there is no point to have the broadcast module at all, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if we want the choke action, then a broadcast module cannot send a message to a peer that has requested us to choke them (this would defeat the purpose of the choking mechanism).

A broadcast module can still decide who to choke, which non choked peers to send a message to, which peers to send IHAVE's to.

Here are some examples of different broadcast strategies that demonstrate the point of the broadcast module:

  • Floodsub-like: Send the direct message to all known peers that are non-choked
  • Episub-Like: Send direct message to all mesh peers that are non-choked
  • Gossipsubv2-like: Pick a random set of mesh peers and send IHAVEs to them, send direct messages to non-choked peers.
  • No Duplicates: Only send IHAVE messages to mesh peers.


### Interface

This section defines the basic logical interface that defines a mesh strategy. The exact API of how a mesh strategy interfaces with the core
Copy link
Contributor

@ppopth ppopth Mar 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This section defines the basic logical interface that defines a mesh strategy. The exact API of how a mesh strategy interfaces with the core
This section defines the basic logical interface that defines a broadcast strategy. The exact API of how a broadcast strategy interfaces with the core


## Interface Implementation

### Publish(Topic) and Forward(Topic)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Publish(Topic) and Forward(Topic)
### Publish(Topic)

@ppopth
Copy link
Contributor

ppopth commented Mar 20, 2025

No, your random choke is not gossipsubv2. They are completely different things. Saying that random choke is gossipsubv2 is very misleading.

In gsv2, when I receive the first IANNOUNCE, I send INEED. If the timeout is triggered, I send INEED to the peer who sent the second IANNOUNCE. An example timeline is as follows.

Let's say the timeout is 500ms
0.0001s - Receive IANNOUNCE from peer1
0.0001s - Send INEED to peer1
0.0100s - Receive IANNOUNCE from peer2
0.5001s - Hasn't received the message from peer1, so the timeout is triggered and send INEED to peer2
0.5101s - Receive the message from peer1
0.5201s - Receive the message from peer2

While in your random choke, the timeline will be different
0.0001s - Receive IHAVE from peer1
0.0001s - Send IWANT to peer1
0.0100s - Receive IHAVE from peer2
0.0100s - Send IWANT to peer2
0.0200s - Receive the message from peer2
0.5101s - Receive the message from peer1

Please also note that with your current generalization, gossipsubv2 strategies cannot be implemented at all.

@AgeManning I encourage you to read the Gossipsub v2 spec to get familiar with the protocol.

@MarcoPolo
Copy link
Contributor

After rereading gsv2 and random choke, it seems like the difference is whether the source or destination controls the push vs pull semantics. In gsv2, the source decides to push the message or rely on the peer to pull the message following an IANNOUNCE. In random choke, the destination decides which peers are choked, and thus which peers will send an IHAVE (pull semantics) rather than push the message.

On the wire, IHAVE/IWANT is roughly equivalent to IANNOUNCE/INEED. The difference is in the semantics of how peers treat these messages. My understanding of this proposal is that it would allow networks to define their own semantics of these messages.

@ppopth
Copy link
Contributor

ppopth commented Mar 20, 2025

the difference is whether the source or destination controls the push vs pull semantics

That's not the only difference. Another one is explained here #664 (comment). The idea is that gsv2 has the timeout which is the core of the improvement.

My understanding of this proposal is that it would allow networks to define their own semantics of these messages.

The problem is that this PR doesn't allow me to do the timeout.

@MarcoPolo
Copy link
Contributor

My understanding is that the timeout could be implemented by the broadcast strategy. From this PR:

On receiving an IHAVE(ids) message, the router will check its seen cache. If the IHAVE message contains message IDs that have not been the router will ask the broadcast strategy whether it should request it via an IWANT message.

That makes it seem that the broadcast strategy could track these IHAVE, request the message immediately, and configure a timeout to try another peer.

@ppopth
Copy link
Contributor

ppopth commented Mar 20, 2025

@MarcoPolo

0.0100s - Receive IANNOUNCE from peer2
0.5001s - Hasn't received the message from peer1, so the timeout is triggered and send INEED to peer2

That would make sense if the generalization allows me to delay answering that question. You can see that I received IANNOUNCE at 0.0100s but decided to send INEED at 0.5001s.

@MarcoPolo
Copy link
Contributor

@AgeManning apologies if this is obvious, but what are the benefits of this spec versus say starting from scratch with knowledge of GossipSub? I don't yet have a strong opinion here. This is not a leading question.

To play devils advocate, in many ways the strategy for mesh and broadcasting is a big part of the solution. If we take that out what is the valuable thing being spec'd here? Is it the control messages? What does an application gain by constraining itself to only these control messages? Is it the interface for the strategies? Is the hope that by defining the interface, applications can build against that and share code with other applications? Are we trying to define high level primitives for any pubsub-like system?

@MarcoPolo
Copy link
Contributor

@MarcoPolo

0.0100s - Receive IANNOUNCE from peer2
0.5001s - Hasn't received the message from peer1, so the timeout is triggered and send INEED to peer2

That would make sense if the generalization allows me to delay answering that question. You can see that I received IANNOUNCE at 0.0100s but decided to send INEED at 0.5001s.

Ah, I think I see your point. Your point is that "random choke" as defined in this PR does not implement this delay. That's true. However, I don't see anything in the "generalized" part that would prohibit a strategy from implementing this delay.

@ppopth
Copy link
Contributor

ppopth commented Mar 21, 2025

However, I don't see anything in the "generalized" part that would prohibit a strategy from implementing this delay.

Let me explain.

That makes it seem that the broadcast strategy could track these IHAVE, request the message immediately, and configure a timeout to try another peer.

The point is how can you try another peer?

One way to do it is when you receive IANNOUNCE from that another peer, the core protocol will invoke the strategy's IHAVE(ids) as defined here and then instead of returning the result of IHAVE(ids) immediately, it will block the function until it knows exactly whether to request the message through IWANT or not.

It will request if the peer before it doesn't respond the message and it won't if the message was received. So it's very unlikely that the node can decide at the time IHAVE(ids) is invoked.

The issue is if the core protocol allows the strategy to block the IHAVE(ids) function or the strategy must return from the function immediately. The core spec should specify whether it allows or not. If not, gsv2 cannot be implemented at all.

Does it make sense?

Disclaimer: I assumed that you cannot arbitrarily send IWANT any time you want. The only way to send it is to tell the core protocol to send it for you through the IHAVE(ids) function.

@MarcoPolo
Copy link
Contributor

Disclaimer: I assumed that you cannot arbitrarily send IWANT any time you want. The only way to send it is to tell the core protocol to send it for you through the IHAVE(ids) function.

I think this is where we interpret the document differently. This highlights the need for more precise language 😄 . I assumed the opposite, that a a strategy could arbitrarily send IWANTs anytime.

@AgeManning
Copy link
Contributor Author

AgeManning commented Mar 24, 2025

Thanks guys.

Keep in mind, this was just a quick writeup to explain the concept, I wouldn't consider it ready to merge and we can change it to adapt to peoples needs.

@pop

No, your random choke is not gossipsubv2. They are completely different things. Saying that random choke is gossipsubv2 is very misleading.

I never said that random choke it is gossipsub v2 (thats why I named it differently), here is what I wrote:

This is an example strategy that resembles the gossipsub v2 proposal (mainly as
an example strategy).

And I do think it resembles gossipsub v2 (which primarily makes a trade-off between direct sending messages in the mesh and gossiping them. It decides this on a per-message basis, with a random factor. As does random-choke, but per mesh-peer rather than message).

@AgeManning I encourage you to read the #653 to get familiar with the protocol.

I have read it, that's why I'm suggesting this (and our long telegram chat).

Let's say the timeout is 500ms
0.0001s - Receive IANNOUNCE from peer1
0.0001s - Send INEED to peer1
0.0100s - Receive IANNOUNCE from peer2
0.5001s - Hasn't received the message from peer1, so the timeout is triggered and send INEED to peer2
0.5101s - Receive the message from peer1
0.5201s - Receive the message from peer2

While in your random choke, the timeline will be different
0.0001s - Receive IHAVE from peer1
0.0001s - Send IWANT to peer1
0.0100s - Receive IHAVE from peer2
0.0100s - Send IWANT to peer2
0.0200s - Receive the message from peer2
0.5101s - Receive the message from peer1

Not sure why the message from peer2 is coming earlier here. But as I explained in the telegram chat, IWANT's also have a timeout that is configurable. It's required from the gossipsub 1.1 spec. If you set that to 500ms, then the IWANT will fail also. If you want to write an implementation that re-requests an IWANT when one expires but from another peer, there is nothing in the specifications from preventing you doing that. If it is a major concern, we can also have an API in a broadcast strategy that decides how to handle failed IWANTs.

That's not the only difference. Another one is explained here #664 (comment). The idea is that gsv2 has the timeout which is the core of the improvement.

Honestly I'm surprised that the core improvement is re-requesting IWANTs. I didn't really think this would have an impact so didn't directly focus on it, I was focused more on the trade-off between the direct vs gossip send in the meshes. I assumed this to be the major change. It would be very easy to re-request IWANTs in our current gossipsub implementation if its core to the improvement.

Disclaimer: I assumed that you cannot arbitrarily send IWANT any time you want. The only way to send it is to tell the core protocol to send it for you through the IHAVE(ids) function.

I didn't think this would be such a big issue. This is just handling "broken promises" (i.e an IWANT response didn't hit its deadline). As I mentioned, anyone can implement this, but if people want it in the spec, I'd suggest just adding an API to handle broken promises to the broadcast module.

Please also note that with your current generalization, gossipsubv2 strategies cannot be implemented at all.

I think the main principle of gossipsubv2 can be implemented. If it is just re-requesting IWANT's that you're concerned about, we can do that. If it's specifically the IANNOUNCE/INEED messages, we can use those instead of CHOKE/UNCHOKE, but I dont think they gain us much and have the following issue:

  • Currently, if you have a set of mesh peers, you would currently expect them to give you messages directly. If you were getting messages slowly, you might consider cycling your mesh peers because they are not performing. It allows you to locally optimize your mesh, and the 1.1 scoring have mechanisms to encourage this. With IANNOUNCE/INEED, you can no longer know if any of your mesh peers are just going to send you messages slowly or if you are randomly unlucky etc. The uncertainty in the mesh, makes it hard to optimize. The CHOKE/UNCHOKE is similar (I won't say the same), but as @MarcoPolo points out, it pushes the knowledge to our peers to gossip rather than direct send. This has the added benefit that, we know at any given time that all our mesh peers will directly send us messages and we know which peers want us to gopssip to.

@MarcoPolo

After rereading gsv2 and random choke, it seems like the difference is whether the source or destination controls the push vs pull semantics.

Exactly.

@AgeManning
Copy link
Contributor Author

@MarcoPolo

@AgeManning apologies if this is obvious, but what are the benefits of this spec versus say starting from scratch with knowledge of GossipSub? I don't yet have a strong opinion here. This is not a leading question.

To play devils advocate, in many ways the strategy for mesh and broadcasting is a big part of the solution. If we take that out what is the valuable thing being spec'd here? Is it the control messages? What does an application gain by constraining itself to only these control messages? Is it the interface for the strategies? Is the hope that by defining the interface, applications can build against that and share code with other applications? Are we trying to define high level primitives for any pubsub-like system?

Yeah good question, I guess I didn't explain it explicitly. There has been out-of-band conversation about this, which is where this originated from.

This adds little to no value in terms of specification (apart from the CHOKE/UNCHOKE, but I'm not entirely convinced we should add them). If you take those messages out, this is exactly the same spec as current gossipsub (as we include current gossipsub broadcast and mesh strategies). So I'm trying to make as little change to gossipsub as possible to avoid building anything new from scratch.

I consider this more of an engineering refactor of code, where we clearly split up parts of the spec that all implementations MUST agree on for the protocol to work, and the other parts where implementations could currently have wildly wrong (they build the mesh incorrectly (not to spec) or send IWANTs for every message etc), or nodes have different configurations (huge mesh degrees) etc and other nodes on the network wouldn't know the difference.

I don't intend this to constrain gossipsub to only these control messages. More control messages can and probably should be added, just as we do with current gossipsub. Even the interface to strategies is unimportant here, because we're not spec'ing cross-client strategies. I don't even expect code sharing.

The value here I think, is to clearly label what MUST be implemented to be part of a gossipsub network (i.e control messages) and what implementers can tweak and modify for their own individual use cases for optimisations and different scenarios.

The thing that has motivated this, was the gossipsubv2 spec, which trades latency for bandwidth. This is an optimisation which has a specific use case. The choice of making this trade-off will be application and network specific. It will be good in some circumstances and bad in others. In general there's a lot more trade-offs that can be made and I'd like us to be able to make other trade-offs and not go too deep down one path.

This PR is proposing to shift the decision of which trade-off to make to be outside of this spec. So every interested party is free to make their own trade-offs without effecting each other. Also if one turns out not to work as expected, its easy to revert and try something else.

For example, an optimization designed for Ethereum doesn't now necessarily affect the filecoin network. Each team are free to choose. Also, it's applied per-topic which allows trade-offs per use (which is important in Ethereum).

The main value in this is deciding what is common in gossipsub across every single party, and what can we split out to so we can individually make our optimisations.

@AgeManning
Copy link
Contributor Author

I was curious about the re-sending of the IWANTs, as I thought I mis-judged the importance of this.

Here is a node running gossipsub on Ethereum mainnet.

It is sending about 1700 IWANT messages every 12 seconds:

iwant

Of those 1700 IWANT messages, barely any are failed to be delivered in time:

promises

As such I've always considered failed IWANT messages to be a low issue, not making a re-send worth it.

@ufarooqstatus
Copy link

ufarooqstatus commented Mar 24, 2025

I was curious about the re-sending of the IWANTs, as I thought I mis-judged the importance of this.

Here is a node running gossipsub on Ethereum mainnet.

It is sending about 1700 IWANT messages every 12 seconds:

Message size raises IWANT request count because sending a large message takes considerable time. During this period, peers already receiving this message may also send IWANT requests (multiple IWANTS in v1.1) for the same message.

The same is the limitation faced by IDONTWANT announcements. A receiver can send IDONTWANTs only after it finishes downloading the entire message. For a large download time, the receiver will likely start receiving the same message from multiple mesh members.

Message preamble is crucial in eliminating these duplicates.

repeated ControlPrune prune = 4;
repeated ControlChoke choke = 5;
repeated ControlUnChoke unchoke = 6;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are additional message proposals that can be valuable for a broader range of GossipSub use cases. For example,

  1. PREAMBLE/IMRECEIVING
    Message preamble enables receivers to learn about ongoing message receptions, and IMRECEIVING requests mesh members to defer sending the same message we are already receiving.

  2. OBSERVE can allow observing a topic without having to download entire messages. Analogous to CHOKE, but allows observing non-mesh members as well

  3. INEED already discussed here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, like the current gossipsub, these are not excluded and can be added as spec changes.

Comment on lines +58 to +72
The generalization proposed here aims to specify these strategies and allow the core protocol
to select each strategy per topic. This allows for scenarios where an
application may have a topic where resiliency is not very important, so a
low-bandwidth strategy could be chosen, (i.e low-mesh, sparse topology) and at
the same time have a topic where resiliency is important so chooses a
high-bandwidth strategy (i.e high-mesh, dense topology).

A node that is heavily resource constrained, might also wish to switch to a
combination of strategies that is known to perform better under those
conditions.

The goal of this protocol is into increase the degrees of freedom in fine-tuning
p2p message dissemination in a general way that doesn't require specification
changes to apply. It also aims to minimize engineering overhead for
implementations that already have gossipsub.
Copy link

@ufarooqstatus ufarooqstatus Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A broader use case encompassing different implementations may still require negotiating around either mesh/forwarding/scoring strategies or the appropriate GossipSub versions.

However, generalizing the GossipSub core and facilitating dynamicity and adaptiveness in mesh/forwarding/scoring strategies would probably encourage the adoption of new techniques with minimal engineering effort.

More importantly, remaining open to incorporating new messages and techniques into the GossipSub core is crucial for the continued growth and evolution of the broader ecosystem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I think we agree here.

@AgeManning
Copy link
Contributor Author

There are have been a number of responses around the core spec proposed here, that have assumed that no additions to the core protocol can be made.

On the contrary, just like the current gossipsub spec, I expect we make spec changes to this to add extra control messages or spec changes and increase the multistream select protocol-id to support this.

I'm not proposing this set if fixed by any means. Simply that we don't necessarily spec the other changes which I'm trying to remove from the spec as "strategies".

mergify bot pushed a commit to libp2p/rust-libp2p that referenced this pull request Apr 17, 2025
As part of working on the [generalized `gossipsub` strategies](libp2p/specs#664) I have been cleaning up code, here follows some of the improvements

Pull-Request: #5991.
mergify bot pushed a commit to libp2p/rust-libp2p that referenced this pull request May 15, 2025
while refactoring scoring for libp2p/specs#664 I recalled #5711 and so this PR changed scope from a refactor to a feature.
Per commit review is suggested for an easier experience.
CC @drHuangMHT

Pull-Request: #6020.
@Nashatyrev
Copy link
Contributor

Interesting proposal.
Absolutely support independent topics flexible configuration.
Not sure about introducing new abstraction level. Probably need to read it more thoughtfully.

BTW we still have multiple topics per message 'feature'. It could complicate the things.
TBH if it's possible I would eliminate this 'flexibility' and leave just single topic per message. It's usually so much hustle from both spec and implementation perspectives.
I know it would be backward incompatible but maybe...
@vyzo by any chance are you aware of real world use cases when this feature makes sense?

@vyzo
Copy link
Contributor

vyzo commented Jun 19, 2025

We killed it a while ago in go-libp2p-pubsub afair, just one topic per message now.

@Nashatyrev
Copy link
Contributor

We killed it a while ago in go-libp2p-pubsub afair, just one topic per message now.

May be we could legitimize it in the spec?

@vyzo
Copy link
Contributor

vyzo commented Jun 19, 2025

Yeah, we should. It doesnt make much sense in any real world applications, and it complicates implementation as well... R.I.P.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Triage
Development

Successfully merging this pull request may close these issues.

6 participants