Show per-message routing info (hop count, multi-path, named repeaters) - #66
Closed
MrSurly wants to merge 4 commits into
Closed
Show per-message routing info (hop count, multi-path, named repeaters)#66MrSurly wants to merge 4 commits into
MrSurly wants to merge 4 commits into
Conversation
Persists path length and SNR from the existing V3 message-receive responses (previously parsed then discarded) onto each Messages row. Adds a (d)/(N) badge next to the sender name and a long-press "Message path" sheet showing a simple sender -> hop count -> you timeline. Named per-hop routing and multi-path duplicate detection (richer data from the raw PUSH_LOG_RX_DATA frame) are deferred -- correlating that frame to a specific decoded message isn't safe with the current sync loop, which can drain multiple queued messages per push.
Adds a message_paths table (one row per distinct radio path a channel message was observed on) populated by correlating raw PUSH_LOG_RX_DATA frames -- previously received but entirely discarded -- against already-decoded channel messages. Correlation works by re-encrypting a message's known plaintext (using its channel's PSK) and finding an exact ciphertext match against buffered raw frames, brute-forcing the 4 possible `attempt` retry values since firmware's decoded response doesn't expose that field. An exact match is unambiguous; no heuristics. Frames sharing the matched packet's hash (payload type + ciphertext, independent of path) are its multi-path siblings -- the same logical packet heard via another route (e.g. direct and relayed at once). Verified end-to-end against live traffic: correctly captured both a direct reception and a relayed one (via a specific repeater hop) for the same message, with real per-hop SNR/RSSI. A DB-level unique constraint on (messageId, pathBytes) makes duplicate-delivery correlation (the same message arriving via push then sync, an existing pattern elsewhere in this file) safe without an application-side race. Also adds getContactsByPublicKeyPrefix (all-matches variant, for later ambiguity display) alongside the existing first-match lookup. UI display of this data is a follow-up; the badge/sheet from the prior commit still uses the single-path Messages.hopCount/snr summary and is unaffected if correlation never matches.
Wires the correlated MessagePaths data (from the previous commit) into the chat UI: - Message path sheet shows every distinct path a message was received on -- each with real SNR/RSSI and named hop(s) resolved against known contacts, falling back to the raw hex identifier when a hop isn't a known contact and to the message-level hopCount/snr summary when no raw-frame correlation exists at all (DMs, or a channel message that never matched). - Ambiguous hops (a short hash prefix matching more than one known contact) show all candidates and are visually flagged. - Chat bubbles now show a MessageHopBadge: the reliable single-value (d)/(N) summary immediately, swapping to a real multi-path summary like (d/1) once correlation data loads for that message -- this was the actual point of the whole effort, not just the detail sheet. - getContactsByPublicKeyPrefix (all-matches) and MessageRepository.getMessagePaths added as plumbing.
MrSurly
marked this pull request as draft
July 19, 2026 03:09
The sheet's content wasn't scrollable, so a path with several hops (e.g. 8) overflowed the bottom of the screen. Caps the sheet at 80% of screen height and wraps content in a scrollable view with a visible scrollbar.
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #65.
Firmware already sends per-message hop count/SNR (in the V3 message-receive responses) and, separately, full per-packet routing data (real per-hop path bytes, RSSI, SNR) in a raw PUSH_LOG_RX_DATA frame -- both were previously parsed and then discarded by this app entirely.
What's new
(d)for direct,(N)for N relay hops, and(d/1)-style when a message was heard via multiple paths at once (e.g. both directly and via a relay).How the richer data is obtained
The raw PUSH_LOG_RX_DATA frame has no ID linking it to the specific decoded message it belongs to -- a single push can precede a sync that returns several queued messages. To correlate them safely: since the app already knows a channel message's exact plaintext (firmware decoded it) and that channel's PSK, it re-encrypts the known plaintext (AES-128-ECB, matching firmware's Utils::encrypt) and looks for an exact ciphertext match against buffered raw frames -- unambiguous, no heuristics. Once matched, every other buffered frame sharing that packet's hash (payload type + ciphertext, independent of path) is a multi-path sibling of the same logical message.
This is channel-messages-only for now -- direct messages use different (asymmetric) crypto not yet implemented here, so DM bubbles/sheets still use the reliable single-value hopCount/snr summary firmware already provides, same as before this PR.
Verified end-to-end against live traffic, including a real multi-path case (a message heard both directly and via a specific named repeater).