From fe5cdc06dd2bfbd81d1f2e92a822fe0a1446fe9d Mon Sep 17 00:00:00 2001 From: 0xSeren <0xseren@tutamail.com> Date: Thu, 16 Apr 2026 17:39:58 -0400 Subject: [PATCH 1/2] fix: enable LoRa CRC on SX127x for RNode interop After reset, SX127x hardware leaves REG_MODEM_CONFIG_2 bit 2 (RxPayloadCrcOn) cleared, and RadioLib's SX127x::begin() does not touch it. Upstream RNode firmware explicitly enables CRC on every LoRa transmit and receive path (sx127x::enableCrc in RNode_Firmware.ino:531, sx127x.cpp:160), so a real RNode will silently drop frames that arrive without a valid CRC. This means T-Beam and LoRa32 V2.1 users running the example LoRaInterface cannot interop with real RNodes over LoRa today: outbound packets are dropped at the RNode, inbound packets may be accepted but silently corrupted. Fix by calling chip->setCRC(true) after SX1276::begin() in the SX127x branch of LoRaInterface::start(). The new call is gated on the prior begin() having succeeded, and its own error is folded into state so the existing RADIOLIB_ERR_NONE check catches it. No change required on the SX126x branches: RadioLib's SX126x::begin() already calls setCRC(2), so RAK4631, Heltec V3, and Heltec V4 inherit CRC-on. --- examples/common/lora_interface/LoRaInterface.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/common/lora_interface/LoRaInterface.cpp b/examples/common/lora_interface/LoRaInterface.cpp index 9cf0279..9d01265 100644 --- a/examples/common/lora_interface/LoRaInterface.cpp +++ b/examples/common/lora_interface/LoRaInterface.cpp @@ -109,6 +109,13 @@ bool LoRaInterface::start() { // begin(freq MHz, bw kHz, sf, cr, syncWord, power dBm, preamble symbols, LNA gain 0=AGC) int state = chip->begin(frequency, bandwidth, spreading, coding, RADIOLIB_SX127X_SYNC_WORD, power, 20, 0); + // SX127x hardware default leaves RxPayloadCrcOn=0 and RadioLib's + // SX127x::begin() does not touch it. Upstream RNode firmware enables + // CRC unconditionally (sx127x::enableCrc, RNode_Firmware.ino:531), so + // real RNodes silently drop frames without a CRC. Enable it here to + // interoperate. SX126x branches below inherit CRC-on from + // SX126x::begin() (setCRC(2)), so no explicit call is needed there. + if (state == RADIOLIB_ERR_NONE) state = chip->setCRC(true); #elif defined(BOARD_RAK4631) // nRF52: SPI pins must be configured before SPI.begin() From b7bde29d615c33ce3ebdc26f02c76753773bfdd3 Mon Sep 17 00:00:00 2001 From: Chad Attermann Date: Tue, 5 May 2026 11:23:18 +0100 Subject: [PATCH 2/2] Corrects announce random hash generation Replaces 10-byte random hash in announce with 5-byte random + 5-byte big-endian timestamp to resolve path issues caused by reliance on timestamp. Suggested fix courtesy of @thatSFguy. --- src/Destination.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Destination.cpp b/src/Destination.cpp index 4259389..c0a60b0 100644 --- a/src/Destination.cpp +++ b/src/Destination.cpp @@ -268,8 +268,16 @@ Packet Destination::announce(const Bytes& app_data, bool path_response, const In else { Bytes destination_hash = _object->_hash; //p random_hash = Identity::get_random_hash()[0:5] << int(time.time()).to_bytes(5, "big") - // CBA TODO add in time to random hash - Bytes random_hash = Cryptography::random(Type::Identity::RANDOM_HASH_LENGTH/8); + // CBA Append 5-byte big-endian timestamp to random_hash + uint64_t now = (uint64_t)OS::time(); + uint8_t time_bytes[5] = { + (uint8_t)((now >> 32) & 0xFF), + (uint8_t)((now >> 24) & 0xFF), + (uint8_t)((now >> 16) & 0xFF), + (uint8_t)((now >> 8) & 0xFF), + (uint8_t)( now & 0xFF) + }; + Bytes random_hash = Cryptography::random(5) + Bytes(time_bytes, 5); Bytes new_app_data(app_data); if (new_app_data.empty() && !_object->_default_app_data.empty()) {