Skip to content

feat: connect-scripts + opt-in route gossip - #125

Merged
M0LTE merged 1 commit into
masterfrom
feat/connect-script-and-route-gossip
May 5, 2026
Merged

feat: connect-scripts + opt-in route gossip#125
M0LTE merged 1 commit into
masterfrom
feat/connect-script-and-route-gossip

Conversation

@M0LTE

@M0LTE M0LTE commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two composing changes:

Connect-scripts automate the operator's manual `C nodeA / C nodeB / DAPPS` chain for reaching a far-end DAPPS peer through a chain of bare packet nodes that don't speak DAPPS or NET/ROM. Script lives on the neighbour row as a list of (send, expect) steps; the daemon plays it before falling into the DAPPSv1 prompt. Used by forwarder, probe, and poll paths.

Route gossip piggybacks a new `routes` command on otherwise-open sessions (push / probe / poll), bounded by a per-(local, remote) staleness gate. Imported routes land in `learnedroutes` with `Source="gossip"`; existing failure-counter machinery handles invalidation. Advertiser filter suppresses unproven routes and never re-exports hearsay (avoids distance-vector loops).

These compose: a connect-script unblocks the cold-start case A→C through bare nodes; gossip then propagates further-reach destinations beyond the manually configured pair.

What's new

  • `DAPPSv1` gains the `routes` verb. Wire form: `route hops=N ageSeconds=N` per line, `end` terminator. Forward-compatible (unknown KVs ignored).
  • `DbNeighbour.ConnectScriptJson` + `DbLearnedRoute.Source` + `DbRouteGossipState` schema additions.
  • `SystemOptions.RouteGossipStalenessHours` (default 6, 0 disables gossip entirely).
  • Dashboard Neighbours panel: connect-script textarea on the add/update form, step-count column on the listing.
  • New docs: `docs/multi-hop.md` covers the through-non-DAPPS-intermediates scenario end-to-end. `implement.md` extended with the `routes` verb. `discovery-and-routing.md` gains a Route gossip section.

Test plan

  • `dotnet build` clean across all projects (dapps.client, dapps.core, dapps.core.tests, harness, uitests, FakeBpqAndDappsClient)
  • `dotnet test`: 584 / 584 passing (565 baseline + 19 new across ConnectScriptTests + RouteGossipTests)
  • `mkdocs build --strict` clean
  • Connect-script: parse round-trip text↔JSON; runner happy-path drives a fake duplex stream and observes substring matches; timeout fires when peer is silent; EOF mid-script throws cleanly; substring matching works across read boundaries
  • Route gossip: staleness gate (never-pulled allows; recent blocks; elapsed re-allows; staleness=0 always blocks); gossip upsert respects traffic priority (won't downgrade a traffic-learned row); rejects self-routes (advertiser advertising themselves); gossip-replaces-gossip resets failure counter on next-hop change
  • Existing routing-algorithm sites (Static, PassiveLearning, FloodFallback, MeshCoreLike) all use the new `RouteBuilder.FromNeighbour` helper so connect-scripts flow through every code path
  • Probe and poll scheduler services pass connect-scripts to NodeProber/NodePoller when the neighbour has one configured
  • Backwards-compatible: existing neighbours with no script behave exactly as before; daemons that don't implement `routes` return `eh?` and senders treat that as "stop trying"

🤖 Generated with Claude Code

Two related changes that compose:

**Connect-scripts** automate the operator's manual
"C nodeA / C nodeB / DAPPS" sequence for reaching a far-end DAPPS
peer through a chain of bare packet nodes that don't speak DAPPS or
NET/ROM. The script lives on the neighbour row as an ordered list of
(send, expect) steps; the daemon plays it over the AGW connection
before falling into the DAPPSv1 prompt. Probe and poll paths use the
same script for consistency. Dashboard form takes the script as
SEND|EXPECT[|TIMEOUT] one step per line; controller validates the
final step lands on DAPPSv1>.

**Route gossip** piggybacks a `routes` exchange on otherwise-open
sessions (push, probe, poll) when a per-(local, remote) staleness
gate allows. Receiver imports advertised destinations into
`learnedroutes` with `Source = "gossip"`; existing failure-counter
machinery handles invalidation. Advertiser filters: only routes with
ConsecutiveFailures=0 that the daemon has actually used; never
re-export gossip-imported rows (avoids distance-vector loops);
manual neighbours always advertised (highest trust). Bounded by
RouteGossipStalenessHours (default 6, 0 disables) - no scheduled
transmission, only piggybacks.

The two compose: a connect-script unblocks the cold-start case (A
manually configured to reach C through a chain), and the routes
piggyback then propagates further reach beyond that initial pair
(C tells A about destinations behind C without further operator
config).

Wire additions:
- DAPPSv1: new `routes` command. Server emits `route <dest> hops=N
  ageSeconds=N` per line, `end` terminator. Forward-compatible:
  unknown KVs ignored, daemons that don't implement it return
  `eh?\n` and senders learn to stop trying.
- BackhaulRoute carries a ConnectScript when the resolved neighbour
  has one; intermediate forwarders see only an opaque session.

Schema additions:
- DbNeighbour.ConnectScriptJson
- DbLearnedRoute.Source ("traffic" | "gossip", default "")
- DbRouteGossipState (per-(local, remote) last-pulled timestamp)
- SystemOptions.RouteGossipStalenessHours

Tests:
- ConnectScriptTests: parse round-trip, runner happy path, timeout,
  EOF mid-script, substring boundary across reads.
- RouteGossipTests: staleness gate (never-pulled / recent / elapsed
  / disabled), upsert priority (gossip vs traffic), self-route
  rejection, gossip-replaces-gossip on next-hop change.

Docs:
- New docs/multi-hop.md covering the through-non-DAPPS-intermediates
  scenario end-to-end.
- docs/implement.md: new `routes` verb section with wire example +
  emission filter.
- docs/discovery-and-routing.md: route gossip section + cross-link
  to multi-hop.
- docs/configure.md: RouteGossipStalenessHours entry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@M0LTE
M0LTE merged commit 3d97502 into master May 5, 2026
6 checks passed
@M0LTE
M0LTE deleted the feat/connect-script-and-route-gossip branch May 5, 2026 21:39
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