feat: add SPREAD anonymous gossip protocol (opt-in)#717
Open
MatheusFranco99 wants to merge 2 commits into
Open
feat: add SPREAD anonymous gossip protocol (opt-in)#717MatheusFranco99 wants to merge 2 commits into
MatheusFranco99 wants to merge 2 commits into
Conversation
SPREAD is an anonymity-preserving, efficiency-oriented gossip mode layered on top of GossipSub. It is fully opt-in: enabled per-router via WithProtocolChoice(SPREAD) and per-message via msg.Spread, and is a no-op for default GossipSub. Core pieces: - spread_state.go / spread_propagation.go: topic-local clustering over Vivaldi network-coordinate distance and the intra/inter-cluster forwarding selector. - vivaldi/: Vivaldi 'height-vector' coordinate service (RTT-estimated proximity) used to derive local clusters. - extensions.go: WithVivaldi / WithSpreadClusteringConfig wiring into the existing peer-extension handshake; SPREAD peers register into spread state once both sides advertise the Spread extension. - gossipsub.go: WithProtocolChoice / WithSpreadPropagationConfig, and the rpcs() hook that replaces the default forwarding set with the SPREAD selection when active (falling back to the default set only if SPREAD selects no peers, so messages are never dropped). - pb/rpc.proto: optional SpreadExtension wire field. - Tests: clustering/config unit tests plus an end-to-end SPREAD selection delivery test. spread.md documents the algorithm; exported symbols carry godoc comments. Co-authored-by: Diogo Cardoso <me@dcard.pt> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The generated code and runtime already rely on SpreadExtension's sourceIsSpreadNode field: gossipsub sets it when forwarding a SPREAD message and pubsub reads it back to keep msg.Spread set on relays, which is what lets SPREAD propagate past the first hop. The .proto, however, declared the message as empty, so regenerating from it would have dropped the field. Declare the field in rpc.proto, regenerate, and drop the now-answered TODO. No wire or behaviour change. Co-authored-by: Diogo Cardoso <me@dcard.pt> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the input - opt-in anonymity would be a valuable addition to Gossipsub. Do you have a longer write-up that explains in more detail how the protocol actually works? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR adds SPREAD, an anonymity-preserving, efficiency-oriented gossip mode layered on top of GossipSub. It is fully opt-in and a complete no-op for default GossipSub:
WithProtocolChoice(SPREAD).msg.Spread.SPREAD biases message forwarding toward a peer's local cluster (peers that are close in network-coordinate space) plus a sampled set of inter-cluster peers, trading a controllable amount of redundancy for reduced source-identifiability while preserving dissemination.
How it works
vivaldi/). A small Vivaldi "height-vector" coordinate service estimates pairwise RTT/proximity by timing a lightweight request/response over a dedicated stream protocol. An optional Newton variant adds robustness checks.spread_state.go,spread_propagation.go). Per topic, SPREAD-capable peers are partitioned into a local cluster (closestClusterPct) and inter-cluster peers (optionally bucketed by angle). The forwarding set is then sampled with configurable intra/inter fanout and probabilities.gossipsub.go). Inrpcs(), when SPREAD is active for a message, the SPREAD-selected peer set replaces the default forwarding set. If SPREAD selects no eligible peers, the router keeps the default GossipSub set, so messages are never dropped.extensions.go,pb/rpc.proto). SPREAD plugs into the existing peer-extension handshake: a peer is registered into SPREAD state only once both sides advertise theSpreadextension. An optionalSpreadExtensionwire field is added to the RPC.Public API
WithProtocolChoice(GOSSIPSUB | SPREAD)WithSpreadPropagationConfig(*SpreadConfig)— intra/inter fanout and probabilitiesWithSpreadClusteringConfig(*SpreadClusteringConfig)— cluster sizing and angular bucketingWithVivaldi(*vivaldi.Service, *VivaldiConfig)— enable network-coordinate estimationvivaldipackage for the coordinate service.All exported symbols carry godoc comments;
spread.mddocuments the algorithm, caching, and selection semantics.Testing
spread_clustering_test.go).TestGossipsubSpreadSelectionDelivers) and the duplicate re-propagation budget.Notes
WithProtocolChoice(SPREAD)is set and messages are explicitly marked.