Skip to content

Adaptive FHSS: authenticated hopset state and commit protocol #263

Description

@josephnef

Summary

Build the deterministic state model and authenticated control protocol for adaptive FHSS hopset changes. This is the protocol foundation for receiver-driven exclusion and later autonomous TX decisions; it does not choose which channels are bad.

Follow-up to #153 / #262. The fixed-hop implementation and measured behavior are documented in docs/fhss.md; adaptive exclusion is its stated next step.

Design

Keep the configured base hopset immutable. Every adaptive state identifies active channels by stable base-hopset bit positions:

struct HopsetState {
    uint32_t epoch;
    uint32_t generation;
    uint64_t active_mask;
    uint64_t activate_round;
};

Derive each round's permutation from (schedule_key, generation, round, active_mask). Including generation ensures a mask change produces a fresh keyed order instead of merely exposing a filtered form of the previous permutation. The schedule remains stateless by absolute slot.

Add versioned authenticated messages:

  • HopsetProposal: epoch, proposed generation/mask, observation count, activation round, reason bitmap, authentication tag.
  • HopsetCommit: epoch, generation, mask, activation round, authentication tag.
  • HopsetStatus: epoch, current generation/mask/round, authentication tag.

TX is the schedule authority: RX proposes; TX validates policy constraints and repeatedly commits; both activate on the announced future round. Derive separate schedule and control keys from DEVOURER_HOP_SEED with explicit domain separation. A schedule fingerprint is not authentication.

Commits must be announced at least 8 rounds ahead and repeated until activation. Acquisition always scans the immutable base hopset; sync/status markers advertise generation and mask fingerprint so an RX that missed the transition can recover. Add infrequent keyed base-hopset rendezvous/probe slots if hardware testing shows acquisition cannot reliably find a reduced set.

Reject stale epochs, replayed/non-monotonic generations, unknown base-hopset fingerprints, activation outside the allowed window, and masks below the configured minimum diversity.

Implementation

  • Extend HopSchedule (or a sibling header-only module) with generation/mask-aware stateless lookup and stable base-hopset indexing.
  • Add dependency-free encode/decode/MAC helpers for the three control messages; do not change caller-owned FEC payload bytes.
  • Extend FHSS sync markers with generation plus active-mask fingerprint while retaining versioned backward rejection.
  • Add structured events for proposal, commit, activation, rejection reason, generation mismatch, and recovery.
  • Document the state machine and wire format in docs/fhss.md.

Acceptance criteria

  • Known-answer tests pin schedule output for fixed key/generation/mask/slot tuples.
  • Every adaptive round covers every active channel exactly once.
  • Two independent instances agree after direct join at a nonzero generation.
  • Tests cover lost, duplicated, reordered, forged, and replayed control frames; TX/RX restart; generation rollover policy; invalid masks; and missed pre-activation commits.
  • A process-level test demonstrates synchronized future-round activation and recovery after one peer misses the commit window.
  • Existing sequential/keyed fixed-hop behavior remains unchanged when adaptive mode is disabled.

Out of scope

  • Deciding which channel to exclude.
  • RF feedback transport policy.
  • Autonomous TX sensing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions