Jonathan BennettandClaude Opus 5 d3b4b343e7 Send an ack over PKC when no channel can carry it (#11891)
* Send an ack over PKC when no channel can carry it

PKI needs only the two keys, so a DM can reach us over a channel we do not
carry. Its ack is a ROUTING packet, which wouldEncryptWithPKC() excludes, so
today it is channel-encoded, fails at setActiveByIndex() with NO_CHANNEL, and is
never sent. The sender sees nothing and retransmits to exhaustion for a message
that was in fact delivered.

Fall back to PKC for exactly that case. This is the one place an ack is
deliberately made opaque to relays; normally that costs next-hop learning and
intermediate retransmission cancel, which is why ROUTING is PKC-excluded in
general, but here there is no readable alternative to lose, because without this
the ack does not exist.

The predicate is scoped as tightly as that argument reaches: a unicast ROUTING
packet we originate, carrying a request_id, to a destination whose key we hold,
under the same ham/sim/private-key preconditions PKC always has, and only when
the channel index does not resolve. It tests channels.getHash() rather than
setActiveByIndex() so it has no side effect; generateHash already returns -1 for
an invalid key, so the two agree on which indexes are unusable.

Four cases in test_packet_signing pin the corners: the fallback fires, it does
not paper over an ack with no destination key, it does not catch a non-ack on
the same unusable channel, and an ack on a channel that does resolve still goes
out readable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012hLcVif8GDEmA2k77hmFG8

* Short-circuit the fallback so an out-of-range channel logs no error

wouldEncryptWithPKC() reaches channels.getName(chIndex) before its portnum
exclusion, and getByIndex() logs "Invalid channel index" on the way past. With
the general predicate tested first, an ack on an out-of-range index printed that
error and then went on to encode successfully. Test ackFallback first so the
case that is about to succeed never asks.

Also record why the range check leads inside the predicate: getHash() is a bare
hashes[i] with no bounds test of its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012hLcVif8GDEmA2k77hmFG8

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-20 05:21:06 +00:00
2026-09-19 06:21:30 -05:00
2026-09-20 04:11:18 +00:00
2021-10-09 17:15:12 +11:00
2026-09-01 18:00:06 -04:00
2024-09-24 15:24:08 -05:00
2026-09-18 16:41:30 +02:00
2026-07-01 19:01:27 -05:00
2026-01-29 10:06:58 -06:00
2024-11-28 06:26:51 -06:00
2024-09-04 15:33:28 -07:00
2026-07-28 11:09:40 +00:00
2026-01-29 10:06:58 -06:00
2026-01-29 10:06:58 -06:00
2026-07-01 19:01:27 -05:00
2025-01-13 12:24:05 +08:00
2026-01-29 10:06:58 -06:00

Meshtastic Logo

Meshtastic Firmware

GitHub release downloads CI CLA assistant Fiscal Contributors Vercel

meshtastic%2Ffirmware | Trendshift

Overview

This repository contains the official device firmware for Meshtastic, an open-source LoRa mesh networking project designed for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware supports various hardware platforms, including ESP32, nRF52, RP2040/RP2350, and Linux-based devices.

Meshtastic enables text messaging, location sharing, and telemetry over a decentralized mesh network, making it ideal for outdoor adventures, emergency preparedness, and remote operations.

Get Started

Join our community and help improve Meshtastic! 🚀

Stats

Alt

S
Description
No description provided
Readme GPL-3.0
251 MiB
0 Stars 1 Watchers 0 Forks
Languages
C++ 73.1%
C 22.1%
Python 2.7%
Shell 1.5%
Batchfile 0.2%
Other 0.2%