Skip to content

feat(net)!: add cold route rank for pop skipping - #2894

Closed
kixelated wants to merge 1 commit into
devfrom
codex/pop-skipping-rank
Closed

feat(net)!: add cold route rank for pop skipping#2894
kixelated wants to merge 1 commit into
devfrom
codex/pop-skipping-rank

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

  • add a Lite06 Cold Route Cost beside marginal Route Cost so a carrying relay keeps a stable per-broadcast rank
  • adopt a warm peer only when its (cold cost, relay hash) rank is strictly lower, and compare warm rank before hop count when marginal costs tie
  • advertise each relay's own cold rank rather than inheriting its active parent, preserving strict descent across transitive warm trees
  • keep IETF and older Lite routes on the existing hash-only compatibility path because those wire formats do not carry cold cost
  • mirror the wire field in js/net and specify it in the moq-lite draft

This replaces the viable remaining rank slice from #2179. The old base/transit-cost prototype was superseded by cumulative Route Cost in #2424 and is now far behind dev. The current design comes from the pop-skipping quest.

Marginal warm discounts intentionally collapse to zero, but that erases the upstream path cost needed to select an aggregation root in asymmetric and simultaneous activation topologies. Cold Route Cost preserves that undiscounted path signal without changing marginal cost as the primary routing metric.

Public API changes

  • Breaking Rust: lite::AnnounceBroadcast::Active and Restart add the required cold: RouteCost field. This is why the PR targets dev.
  • Additive TypeScript: active and restart AnnounceBroadcast variants add optional cold?: bigint.
  • The routing model's cold bookkeeping remains pub(crate); no second public broadcast::Route metric is exposed.

Test plan

  • nix develop --command just fix
  • nix develop --command just check
  • nix develop --command cargo test -p moq-net (864 unit tests plus integration and docs)
  • nix develop --command bun test js/net/src/lite/announce.test.ts
  • nix develop --command just test smoke-full (21 Rust/Python/JS/C/GStreamer combinations)

Cross-package sync: updated js/net and drafts/draft-lcurley-moq-lite.md. There is no existing doc/concept route-selection page to update. The IETF cluster wire is intentionally unchanged because the current quest rollout is Lite06-only.

(Written by GPT-5)

Co-Authored-By: GPT-5 <noreply@openai.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Superseded by #2925.

The diagnosis here is right and I kept it: once two relays both carry a broadcast they both advertise 0, marginal cost ties, and the hash picks the aggregation root at random. The undiscounted path cost is the signal that breaks that tie, and no receiver can derive it locally, so it does have to go on the wire.

What changed is the shape. #2925 makes the route cost a pair (Cost { warm, cold }) rather than adding cold and advertised_cold beside the existing cost and advertised. Because the pair derives Ord in field order, the cold tie-break falls out of the existing ordering with no new code: route_order is untouched, there is no rank parameter to thread through selection, and own_rank() no longer runs a min over every route inside min_by_key. Route keeps the field count it had, with_cost keeps its call sites, and the hand-written Default goes away.

The Options go away too, by fixing something this PR got wrong: a wire that cannot express a cold cost has to read as the saturation ceiling, not as 0. At 0 a peer that told us nothing looks like the publisher itself and outranks every relay that told the truth, so a mixed-version mesh drags its aggregation point onto whichever peer said the least. At the ceiling it ties against other unknowns and falls through to the hash, which is exactly the old behavior, and the fallback branch in the gate is no longer needed.

One more difference worth flagging: the rank this PR advertises is a min over all announced routes, which is not necessarily the route the relay serves from, so it can advertise a cold cost it is not actually paying. #2925 ranks on the serving route's cold cost, which is what makes the descent argument hold — adopting a parent charges that link onto your own cold cost, so you can only ever rank above the relay you adopted.

Closing in favor of #2925.

(written by Opus 5)

@kixelated kixelated closed this Aug 18, 2026
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.

1 participant