Back to list
Development Update — August 9
Today’s work lays the groundwork for a structural change in how the network uses dmsg. For most of Skywire’s life a visor stays permanently attached to a star of public dmsg servers, and the deployment services live behind those servers too — a topology that concentrates connection churn and handshake cost onto a handful of hosts. The design landing today reframes dmsg as a bootstrap-only floor: something a visor leans on to get its first transports, then increasingly bypasses by relaying for its peers over the transports it already has. Two of the four RFC components ship as running code — the idle-session reaper and always-on server relaying — alongside two empirical findings that decide how the deployment feeds eventually move off the dmsg-server star.
Skywire: dmsg as a Bootstrap Floor
3811 docs(design): RFC — dmsg as a bootstrap-only floor is the framing document, docs/design/dmsg-bootstrap-floor.md. It covers all four components and, in depth, the hard part: moving the deployment services off dmsg-server dependence by forwarding each service’s local CXO listener over skynet from a co-located visor, plus a <PK>:<port> route-dialing RoundTripper behind a new getHTTPClient scheme branch — persistent rather than stateless HTTP proxying, and paradox-free because the service stays a plain process while the forwarding visor bootstraps over the dmsg floor. 3810 feat(dmsg): idle-session reaper is the first component in code. A dmsg client’s initial connect stops at MinSessions, but the dial path opens on-demand rendezvous sessions to reach a peer delegated to a server the client wasn’t connected to, and pingSessionsLoop then keeps those alive forever — so the session count drifts up toward “all servers” over the process lifetime (observed live: visors on 7 servers with sessions_count=2), which is real recurring fleet bandwidth. A new reapIdleSessionsLoop closes sessions that have read as streamless (NumStreams()==0) for ≥2 consecutive 60s checks and are beyond MinSessions, never below the floor; in-use sessions are never touched, quic’s unknown stream count (-1) is treated as busy so nothing is reaped on a guess, and a reaped session is simply re-dialed on demand if traffic to that peer resumes. The decision is factored into a pure, unit-tested pickIdleSessionsToReap.
3812 feat(dmsg): always-on server↔server relay makes peer relaying simply how a dmsg server behaves. A server already forwards between clients on different servers via forwardViaPeer/PeerAnnounce — no routing needed, the destination PK is the address, resolved by one map lookup plus a byte-splice — but that shipped opt-in behind AnnounceAsPeer/AcceptPeerAnnouncements, both default off, fragmenting the fleet into “relays” and “non-relays” for no good reason. Both toggles are removed; every server now announces itself as a forwardable peer and honors inbound announcements unconditionally. Because an always-open relay surface can’t be allowed to become an amplifier, it’s bounded: max_peer_links (512) caps concurrent peer sessions and max_relayed_streams (4096) caps streams bridged on behalf of a peer — counted only when one side is a peer session, so plain local client↔client bridging is never gated — enforced by an atomic slot counter returning ErrRelayCapacityReached at the cap, with the existing 1-hop loop guard unchanged. accepted_peer_pks survives as an optional allowlist that only narrows who may be filed as a peer; there is no toggle to disable relaying.
Skywire: CXO Presence Is Not Transitive
3813 docs(dmsg): CXO relay presence finding + signed-heartbeat uptime extends the RFC with two empirically-grounded findings, plus a characterization test that pins the behavior so a future change to relay semantics is a deliberate, visible decision. First, CXO propagates as a subscription tree, not gossip: a node relays a feed only if it itself subscribed to it (broadcastRoot re-sends a Root to every other subscriber of that feed), so propagation follows the subscription graph, not the transport graph — which means visor→deployment is irreducible fan-in (N feeds; relays cut connections and noise handshakes, not feed count), while deployment→fleet is one aggregated feed fanning out over a cheap tree, and that is where a relay-visor tier genuinely replaces the dmsg-server star. Second, presence is not transitive through a relay, so uptime can’t ride connection lifetime behind one. CXO relaying is store-and-forward — each hop terminates the upstream conn and re-originates downstream — so a relay’s knowledge that an origin went offline does not reach nodes behind it. The new TestRelayPresenceNotTransitive measures exactly this: with V → R → A plus a direct control edge V → A2, killing V fires OnDisconnect on A2 and R immediately but A gets nothing. So behind the relay tier, uptime inverts from detecting absence to confirming presence: a visor republishes its signed, timestamped head Root periodically — a Root already carries Seq/Time/Sig, unchanged children are content-addressed and dedup, so the beat costs about one small Root, relays can’t forge it, and a vanished visor times out. It reuses machinery the project already has in the SD/uptime idle-republish tickers.