From 94ed729985fec83267df2b61b73d5c018ef2736f Mon Sep 17 00:00:00 2001 From: PacoX Date: Wed, 13 May 2026 10:43:57 +0200 Subject: [PATCH] bug fix --- documentation/routing-paths.md | 11 ++++++----- lib/screens/path_trace_map.dart | 29 ++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/documentation/routing-paths.md b/documentation/routing-paths.md index 1de549bd..83d297a3 100644 --- a/documentation/routing-paths.md +++ b/documentation/routing-paths.md @@ -15,7 +15,6 @@ The device capability determines the hash width (number of bytes per hop): | 1 byte | 256 | Single-byte node IDs | | 2 bytes | 65,536 | Medium meshes | | 3 bytes | 16.7M | Large networks | -| 4 bytes | 4.3B | Gigantic deployments | ### Device Capability Detection @@ -23,13 +22,15 @@ On device connection, the app reads the firmware capability to set `pathHashByte ```dart // Read from device info response (offset 81) -final modeRaw = firmwareBytes.length >= 82 - ? (firmwareBytes[81] & 0x3F) +final modeRaw = firmwareBytes.length >= 82 + ? (firmwareBytes[81] & 0xFF) : 0; -final mode = modeRaw.clamp(0, 3); -_pathHashByteWidth = mode + 1; // 1, 2, 3, or 4 bytes per hop +final mode = modeRaw.clamp(0, 2); +_pathHashByteWidth = mode + 1; // 1, 2, or 3 bytes per hop ``` +The current implementation intentionally clamps to modes `0..2`, so the supported hop width is `1..3` bytes. Do not document 4-byte hops unless the connector implementation is widened first. + ### Path Data Structure Paths in messages and storage consist of: diff --git a/lib/screens/path_trace_map.dart b/lib/screens/path_trace_map.dart index 3bf1e7e3..34690a8b 100644 --- a/lib/screens/path_trace_map.dart +++ b/lib/screens/path_trace_map.dart @@ -51,6 +51,12 @@ class PathTraceData { String _hopKey(Uint8List hopBytes) => PathHelper.formatHopHex(hopBytes); +Uint8List _lastHopChunk(Uint8List path, int hopWidth) { + if (path.isEmpty) return Uint8List(0); + final width = hopWidth.clamp(1, path.length); + return Uint8List.fromList(path.sublist(path.length - width)); +} + class PathTraceMapScreen extends StatefulWidget { final String title; final Uint8List path; @@ -208,8 +214,9 @@ class _PathTraceMapScreenState extends State { } final mirroredHops = [...pathHops]; - if (widget.targetContact?.type == advTypeRepeater || - widget.targetContact?.type == advTypeRoom) { + final isRepeaterOrRoom = widget.targetContact?.type == advTypeRepeater || + widget.targetContact?.type == advTypeRoom; + if (isRepeaterOrRoom) { final pk = widget.targetContact?.publicKey; if (pk != null && pk.length >= hopWidth) { mirroredHops.add(Uint8List.fromList(pk.sublist(0, hopWidth))); @@ -220,8 +227,16 @@ class _PathTraceMapScreenState extends State { ), ); } + // For repeaters/rooms, include full reversed path + mirroredHops.addAll(pathHops.reversed); + } else { + // For non-repeater/room targets, reverse without duplicating the pivot hop + if (pathHops.length > 1) { + mirroredHops.addAll( + pathHops.sublist(0, pathHops.length - 1).reversed, + ); + } } - mirroredHops.addAll(pathHops.reversed); final traceBytes = []; for (final hop in mirroredHops) { @@ -396,7 +411,8 @@ class _PathTraceMapScreenState extends State { (c) => c.hasLocation && c.path.isNotEmpty && - _hopKey(Uint8List.fromList([c.path.last])) == hopKey, + _hopKey(_lastHopChunk(c.path, widget.pathHashByteWidth)) == + hopKey, ) .toList(); if (peers.isNotEmpty) { @@ -442,7 +458,10 @@ class _PathTraceMapScreenState extends State { (c) => c.hasLocation && c.path.isNotEmpty && - _hopKey(Uint8List.fromList([c.path.last])) == lastHopKey, + _hopKey( + _lastHopChunk(c.path, widget.pathHashByteWidth), + ) == + lastHopKey, ) .toList(); if (peers.isNotEmpty) {