Skip to content

add SWIP-60: BPS singlehop — brokered broadcast pub/sub, base protocol - #104

Open
zelig wants to merge 4 commits into
masterfrom
swip-60-bps-singlehop
Open

add SWIP-60: BPS singlehop — brokered broadcast pub/sub, base protocol#104
zelig wants to merge 4 commits into
masterfrom
swip-60-bps-singlehop

Conversation

@zelig

@zelig zelig commented Aug 3, 2026

Copy link
Copy Markdown
Member

Base SWIP of the Broadcast Pub/Sub (BPS) family — the decomposition of the monolithic PubSub SWIP (#93) into work-package-sized SWIPs.

What it specifies: the smallest complete BPS protocol — one broker per topic, direct long-lived p2p streams, an explicit per-topic connection cap, SOC-only messages verified end-to-end. A cohort is fully described by a CohortSpec of genesis parameters; modes are parameter combinations, not an enum. Companion wire spec: assets/swip-60/bps.proto (singlehop concrete; multihop control frames reserved).

Deliberately out of scope (own SWIPs): multihop relaying/referral, reorganisation policies (SWATCH, SPORE), bandwidth incentives, broker discovery (SWIP-59 MEX, #103), history delivery, implicit-publisher event sourcing.

Relation to #93: this SWIP absorbs its Milestone 1 plus the mode system (reframed as genesis parameters); Milestone 3 was already extracted as SWIP-59 (#103). Implementation groundwork: bee #5435, bee-js #1151.

🤖 Generated with Claude Code

Base SWIP of the Broadcast Pub/Sub (BPS) family — the decomposition of the
monolithic PubSub SWIP (PR #93) into work-package-sized SWIPs. Companion
wire spec: assets/swip-60/bps.proto (singlehop concrete, multihop control
frames reserved).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@zelig zelig mentioned this pull request Aug 3, 2026
@zelig zelig self-assigned this Aug 3, 2026
Comment thread SWIPs/assets/swip-60/bps.proto Outdated

// What the topic binds to (see epic: "What does the topic bind to?").
enum TopicBinding {
TOPIC_BINDING_UNSPECIFIED = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what does this semantically mean? why is this a legitimate value that can be used?

Comment thread SWIPs/assets/swip-60/bps.proto Outdated

// Who may author (see epic: genesis dimensions).
enum PublisherRegime {
PUBLISHER_REGIME_UNSPECIFIED = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what does this semantically mean? why is this a legitimate value that can be used?

Comment thread SWIPs/assets/swip-60/bps.proto Outdated
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_*

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

if EXPLICIT_LIST is this then a concatenated list of ethereum keys?

EXPLICIT_SINGLE = 1; // opener is admin and sole publisher (live streaming)
EXPLICIT_LIST = 2; // admin dictates who the other publishers are
IMPLICIT = 3; // authorship implied by the topic binding (PO constraint)
ALL = 4; // every peer publishes (gossipsub-equivalent cohort)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why do we need this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The 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 .

Comment thread SWIPs/assets/swip-60/bps.proto Outdated
bool history = 4; // deliver matching chunks from the local store
bytes admin = 5; // 20-byte eth address; set iff EXPLICIT_*
uint32 po_min = 6; // proximity order for implicit bindings (default 16)
uint32 cap = 7; // max direct streams the broker accepts for this topic (0 = broker default)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why should a 3rd party be able to control the number of connections on a remote peer? what if the number is too large for the remote node to accept?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fair enough i dont think it should

Comment thread SWIPs/assets/swip-60/bps.proto Outdated
message Broadcast {
oneof frame {
Soc handshake = 1; // first frame on a stream: full SOC identity
DataFrame data = 2; // subsequent frames: signature ‖ span ‖ payload only

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why split the same chunk to multiple messages? you're also overloading the protocol code to do the message sequencing/buffering/etc... seems really unnecessary. also if you assume just one stream per topic then essentially you're coercing the applications to manage multiple streams between the same two peers continuously - why not multiplex everything over the same stream?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

while the single/multiple stream part is debatable, i'm not sure we need to skimp out on these few bytes that the chunk carries - it really doesn't save much, and then if we want to do single/multi stream management, we don't have to break the message format

Comment thread SWIPs/assets/swip-60/bps.proto Outdated
oneof frame {
Soc handshake = 1; // first frame on a stream: full SOC identity
DataFrame data = 2; // subsequent frames: signature ‖ span ‖ payload only
Ping ping = 3; // keepalive; parent measures RTT off the echo

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

who needs this information? we already measure rtt using other means. not sure why this message is needed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fair, it is not

Comment thread SWIPs/swip-60.md

## Out of scope (deliberately)

Multihop relaying and referral (bps-multihop), reorganisation policies (SWATCH, SPORE —

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

i would also add to this: remove multi-publisher setup from this iteration. it can be added later and just adds more review surface to deal with at this moment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

funnily i think a single one only is more complex to implement since you need to authenticate.

Comment thread SWIPs/assets/swip-60/bps.proto Outdated
enum PublisherRegime {
PUBLISHER_REGIME_UNSPECIFIED = 0;
EXPLICIT_SINGLE = 1; // opener is admin and sole publisher (live streaming)
EXPLICIT_LIST = 2; // admin dictates who the other publishers are

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

i would get rid of this for a first iteration

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alright , but then you cannot get rid of ALL, otherwise you cannot have collab eediting..see below

// ---------------------------------------------------------------------------

// What the topic binds to (see epic: "What does the topic bind to?").
enum TopicBinding {

Copy link
Copy Markdown

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...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

  • confusing, not very approachable, does not make sense, very dumb, no topic semantics, hmmm, thats a lot of negative things to asspciated to something that could have different semantics according to its type which makes for a... complex API surfaces? hhwhhat?

@acud acud Aug 5, 2026

Copy link
Copy Markdown

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

Copy link
Copy Markdown
Member Author

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?

Copy link
Copy Markdown
Member Author

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

- Connect split into Open (opener fixes CohortSpec) / Subscribe (topic only,
  no cohort metadata); broker Ack echoes the spec to subscribers for
  end-to-end verification; Role enum gone
- broker capacity removed from CohortSpec: broker-side policy, not a cohort
  parameter; jam-cohort seat bound now = genesis publisher list
- EXPLICIT_LIST mechanics specified: repeated publisher_list fixed at
  genesis; dynamic grants/revocations deferred (out of scope)
- every frame carries the full SOC: handshake/data split dropped;
  stream-model rationale added (per-topic streams, mux-migration safe)
- Ping dropped: liveness/RTT are transport concerns
- *_UNSPECIFIED enum zero values documented as invalid on the wire

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@zelig

zelig commented Aug 4, 2026

Copy link
Copy Markdown
Member Author

Revision 2 pushed (25f6f08), addressing the review:

Taken:

  • Connect split into Open (the opener fixes the CohortSpec) and Subscribe (topic only — subscribers carry no cohort metadata). The broker's Ack echoes the spec back so subscribers can verify every message end-to-end. The Role enum is gone with the split.
  • Capacity is out of CohortSpec — agreed a cohort shouldn't dictate a remote node's connection count. It's broker-side policy now; FULL semantics unchanged. The jam-cohort seat bound comes from the genesis publisher list instead.
  • Handshake/data frame split dropped — every frame carries the full SOC, so no sequencing state and no format break if the stream model changes later. Kept one stream per (peer, topic) for now, with the rationale spelled out in the wire section (per-cohort flow control/teardown, bee protocol idiom; mux migration stays format-compatible).
  • Ping dropped — liveness/RTT are transport concerns.
  • *_UNSPECIFIED = 0: documented in the proto header — proto3 requires a zero value; it is deliberately invalid on the wire so nothing can rely on a default.

Specified (was a gap): EXPLICIT_LIST is a repeated publisher_list fixed at genesis — not concatenated bytes. Dynamic grants/revocations are explicitly out of scope for this iteration, which trims the review surface without dropping multi-publisher.

Kept, per the discussion above: TopicBinding and the multi-publisher regimes (EXPLICIT_LIST/ALL) — the closed collab-editing cohort is a headline use case, and single-publisher-only wouldn't even be simpler, since publisher authentication is needed regardless.

🤖 Generated with Claude Code

@zelig
zelig marked this pull request as ready for review August 4, 2026 23:17
Copilot AI lite review requested due to automatic review settings August 4, 2026 23:17
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds SWIP-60 as the base specification for the Broadcast Pub/Sub (BPS) “singlehop” protocol, including its cohort-genesis parameters, roles/capacity semantics, framing model, and a companion protobuf wire definition to enable interoperable implementations.

Changes:

  • Introduces the SWIP-60 markdown specification describing singlehop brokered broadcast pub/sub semantics and conformance criteria.
  • Adds bps.proto defining the protocol messages/types for pubsub/1.0.0 (Open/Subscribe/Ack + SOC-only Publish/Broadcast).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
SWIPs/swip-60.md New SWIP-60 spec text describing cohort parameters, singlehop flow, and conformance expectations.
SWIPs/assets/swip-60/bps.proto New protobuf schema for the SWIP-60 wire messages and cohort specification.
Suppressed comments (1)

SWIPs/assets/swip-60/bps.proto:131

  • The comment says "2–15 reserved", which can be read as protobuf reserved (meaning the numbers must never be used) even though the intent appears to be "kept for future multihop fields". Rewording avoids confusion for readers and implementers generating code from the schema.
    // 2–15 reserved: multihop control plane (Beacon, Reparent, Expect,
    // DcutrSignal, SwapProposal) — named to fix intent, not final.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread SWIPs/swip-60.md
| `publishers` | `EXPLICIT_SINGLE` / `EXPLICIT_LIST` / `IMPLICIT` / `ALL` | who may author |
| `admin` + `publisher_list` | eth addresses | set iff explicit publishers; with `EXPLICIT_LIST` the full publisher set is **fixed at genesis** (dynamic grants/revocations are deferred to a later revision) |
| `history` | bool | deliver matching chunks already in the local store (mechanism in bps-history; a singlehop broker MAY refuse) |
| `po_min` | uint (default 16) | proximity constraint for implicit bindings: `PO(socAddr, anchor) ≥ po_min` |

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

po_min should be a constant not. a param

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
uint32 po_min = 7; // proximity order for implicit bindings (default 16)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants