fix(ui): multi-byte path rendering across contact list, DM modal, retry

Same root cause as the previous console fix: meshcore lib 2.x stores
out_path_len as the masked hop count and out_path_hash_mode separately.
Several UI surfaces and the DM retry logic were still decoding the
hash-size mode from the upper bits of out_path_len, which always yields
1 for in-memory contact data and silently truncates multi-byte paths.

Fixed sites:
- /api/contacts/detailed: path_or_mode and outgoing payload now use
  out_path_hash_mode; the field is included in /api/contacts too.
- dm.js: Contact Info modal computes hashSize for the import button
  from out_path_hash_mode.
- console "contacts" command: same correction as "path".
- device_manager._paths_match / _extract_path_hex: accept hash mode as
  a parameter; callers (_dm_retry_task, _delayed_path_backfill, Phase 2
  rotation dedup) pass contact.out_path_hash_mode.
- PATH event handlers: derive hash_size from path_hash_mode instead of
  decoding it from an already-masked path_len.
This commit is contained in:
MarekWo
2026-06-05 08:54:29 +02:00
parent fecf8cdccb
commit 4effa47fe1
4 changed files with 61 additions and 38 deletions
+6 -5
View File
@@ -486,12 +486,13 @@ def _execute_console_command(args: list) -> str:
pk_short = pk[:12]
opl = c.get('out_path_len', -1)
if opl > 0:
# Decode path: lower 6 bits = hop count, upper 2 bits = hash_size-1
hop_count = opl & 0x3F
hash_size = (opl >> 6) + 1
raw = c.get('out_path', '')
meaningful = raw[:hop_count * hash_size * 2]
# meshcore lib 2.x: out_path_len holds hop count; mode is in out_path_hash_mode
hop_count = opl
hash_mode = c.get('out_path_hash_mode', 0)
hash_size = max(1, hash_mode + 1) if hash_mode >= 0 else 1
chunk = hash_size * 2
raw = c.get('out_path', '')
meaningful = raw[:hop_count * chunk]
hops = [meaningful[i:i+chunk].upper() for i in range(0, len(meaningful), chunk)]
path_str = ','.join(hops) if hops else f'len:{opl}'
elif opl == 0: