-
Notifications
You must be signed in to change notification settings - Fork 33
SWIP-060: BPS singlehop — brokered broadcast pub/sub, base protocol #104
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
base: master
Are you sure you want to change the base?
Changes from all commits
d0fd952
25f6f08
77f6088
7481286
22e8325
4ea5c9e
98e8918
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| // Broadcast Pub/Sub (BPS) — protocol messages and types. | ||
| // Spec: SWIP-60 (../../swip-60.md). | ||
| // | ||
| // Revision 2 (2026-08-05), after review on PR #104: Connect split into | ||
| // Open/Subscribe (subscribers carry no cohort metadata), broker capacity | ||
| // removed from CohortSpec (it is broker-side policy, not a cohort parameter), | ||
| // Ping dropped (liveness/RTT are transport concerns), and every frame carries | ||
| // the full SOC (no handshake/data split). Field numbers renumbered — the | ||
| // draft has no deployed compatibility surface. | ||
| // | ||
| // Enum zero values (*_UNSPECIFIED): proto3 requires a zero value; it is | ||
| // deliberately NOT a legitimate wire value. It exists so that an unset field | ||
| // is detectable and no implementation can silently rely on a default. | ||
| // Receivers MUST reject messages carrying it. | ||
| // | ||
| // The singlehop (depth = 1) subset is concrete; multihop control-plane | ||
| // messages are reserved. Implementation groundwork: bee PR #5435 | ||
| // (hand-rolled byte framing with the same semantics). | ||
|
|
||
| syntax = "proto3"; | ||
| package bps; | ||
|
|
||
| option go_package = "github.com/ethersphere/bee/v2/pkg/bps/pb"; | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Cohort genesis — the primitive decisions whose combinations are the "modes" | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| // What the topic binds to (see SWIP-60: binding semantics). | ||
| enum TopicBinding { | ||
| TOPIC_BINDING_UNSPECIFIED = 0; // invalid on the wire (see header note) | ||
| ANCHOR = 1; // topic = full SOC/GSOC address; dedup on the wrapped CAC | ||
| SOC_ID = 2; // topic = SOC id; any owner with PO(addr, anchor) >= PO_MIN | ||
| OWNER = 3; // topic = SOC owner; any id with PO(addr, anchor) >= PO_MIN (MIC) | ||
| FEED_TOPIC = 4; // id = keccak256(topic ‖ index); graffiti MIC / feed streams | ||
| } | ||
|
|
||
| // Who may author. | ||
| enum PublisherRegime { | ||
| PUBLISHER_REGIME_UNSPECIFIED = 0; // invalid on the wire (see header note) | ||
| EXPLICIT_SINGLE = 1; // opener is the sole publisher (live streaming) | ||
| EXPLICIT_LIST = 2; // set fixed at genesis: admin + publisher_list | ||
| // (dynamic grants/revocations: later revision) | ||
| IMPLICIT = 3; // authorship implied by the topic binding (PO constraint) | ||
| ALL = 4; // every peer publishes (gossipsub-equivalent cohort) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. either ALL or EXPLICIT list needed. HOnestly I do not find it very natural that you can edit a file ith 3 other random people :) you want to restrict, explicitly list those that do . |
||
| } | ||
|
|
||
| // Fixed by the cohort's opener; immutable for the cohort's lifetime. | ||
| // NOTE: broker capacity is NOT a cohort parameter — a cohort cannot dictate a | ||
| // remote node's connection count. Each broker enforces its own per-topic | ||
| // stream limit and answers FULL when it is exhausted. | ||
| // NOTE: the proximity constraint for implicit bindings is a protocol | ||
| // constant, PO_MIN = 16 — not a cohort parameter (a proto3 unset uint32 is | ||
| // indistinguishable from 0, which would silently disable the constraint; | ||
| // and no use case varies it). | ||
| message CohortSpec { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment is misleading and partially incorrect. the seq diagram in the markdown file defines that actually both publisher and subscriber use the same type of message to connect to a broker. i'm not sure what are my feelings around this. it seems to be too elaborate for both sides to use symmetrically - why does a subscriber need to provide the whole so it begs the question, why shouldn't a state channel opening become its own specific message? and then equally |
||
| bytes topic = 1; // 32 bytes, meaning per binding | ||
| TopicBinding binding = 2; | ||
| PublisherRegime publishers = 3; | ||
| bool history = 4; // deliver matching chunks from the local store | ||
| bytes admin = 5; // 20-byte eth address; set iff EXPLICIT_* | ||
| repeated bytes publisher_list = 6; // 20-byte eth addresses, excl. admin; | ||
| // set iff EXPLICIT_LIST | ||
| reserved 7; // was po_min — now protocol constant PO_MIN | ||
| bool closed = 8; // no audience: subscribers restricted to the publishers | ||
| } | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Stream establishment, stream name "pubsub/1.0.0" — one stream per (peer, topic). | ||
| // The first message on a fresh stream is Open (fixes a new cohort) or | ||
| // Subscribe (joins an existing one); the broker answers with Ack. | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| // Opener -> broker: the one peer that fixes the cohort. | ||
| message Open { | ||
| CohortSpec cohort = 1; | ||
| PublisherAuth auth = 2; // present iff the opener publishes (explicit regimes) | ||
| } | ||
|
|
||
| // Joiner -> broker: names the topic — nothing more. Subscribers carry no | ||
| // cohort metadata; auth is present iff the joiner publishes (publishers | ||
| // connect directly to the broker). | ||
| message Subscribe { | ||
| bytes topic = 1; // 32 bytes | ||
| PublisherAuth auth = 2; // present iff publisher | ||
| } | ||
|
|
||
| message PublisherAuth { | ||
| bytes owner = 1; // 20-byte eth address of the SOC owner key | ||
| bytes id = 2; // 32-byte SOC id, when the binding fixes it | ||
| } | ||
|
|
||
| // Broker -> peer, answering Open or Subscribe. The echoed CohortSpec lets a | ||
| // subscriber verify every message end-to-end against the topic binding. | ||
| message Ack { | ||
| Status status = 1; | ||
| CohortSpec cohort = 2; // set iff status == OK | ||
| } | ||
|
|
||
| enum Status { | ||
| STATUS_UNSPECIFIED = 0; // invalid on the wire (see header note) | ||
| OK = 1; | ||
| FULL = 2; // broker at its per-topic capacity; | ||
| // a singlehop broker refuses — nothing else | ||
| UNKNOWN_TOPIC = 3; // Subscribe for a topic the broker does not serve | ||
| REJECTED = 4; // e.g. publisher not on the list, invalid auth, | ||
| // non-publisher Subscribe on a closed cohort | ||
| } | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Messages — SOC-only is a protocol feature | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| // A full single-owner chunk in transit. Every frame is self-contained: no | ||
| // per-stream handshake state, and no format change if the stream model | ||
| // evolves (e.g. topic-muxed streams later). | ||
| message Soc { | ||
| bytes id = 1; // 32 bytes | ||
| bytes owner = 2; // 20 bytes (recoverable from signature; explicit for cheap filtering) | ||
| bytes signature = 3; // 65 bytes | ||
| bytes span = 4; // 8 bytes LE | ||
| bytes payload = 5; // wrapped-CAC data, <= 4096 bytes | ||
| } | ||
|
|
||
| // Publisher -> broker. | ||
| message Publish { | ||
| Soc soc = 1; | ||
| } | ||
|
|
||
| // Broker -> subscriber. | ||
| message Broadcast { | ||
| oneof frame { | ||
| Soc soc = 1; | ||
| // 2–15 reserved: multihop control plane (Beacon, Reparent, Expect, | ||
| // DcutrSignal, SwapProposal) — named to fix intent, not final. | ||
| } | ||
| } | ||
|
|
||
| // Keepalive / RTT: none at the BPS level. Liveness is the transport's job | ||
| // (libp2p), and latency metrics for reorganisation policies (SWATCH) are | ||
| // sourced there as well. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: i find this whole thing really confusing and not very approachable and i wonder if this even makes sense to do in a first iteration. "pubsub" is very dumb in this sense - it usually does not give you different topic semantics. here, a topic could have different semantics and input validation according to its "type" which makes for a much more complex API surfaces for users later on...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i meant the concept of pubsub usually does not offer different semantics over the concept of a topic. i would appreciate you not hijacking my words and initial intention as this is really counter productive and aggressive. thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quoted your words which indeed were unnecessarily agressive.
As for your original intention, what was it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure the semantics of topic or pubsub changes here, I thinkk the various bindings merely link the updates on a topic differently to each other as well as allow for multiple sources