Skip to content
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 33 additions & 17 deletions src/mesh/NodeDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2425,6 +2425,10 @@ void NodeDB::loadFromDisk()
warmStore.load();
#endif

// Set when devicestate is discarded below; consumed after config is loaded (see the
// deferred owner recovery further down).
bool ownerRecoveryPending = false;

// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
state = loadProto(deviceStateFileName, meshtastic_DeviceState_size, sizeof(meshtastic_DeviceState),
&meshtastic_DeviceState_msg, &devicestate);
Expand All @@ -2441,23 +2445,9 @@ void NodeDB::loadFromDisk()
LOG_WARN("Devicestate %d is old or invalid, discard", devicestate.version);
installDefaultDeviceState();

// Attempt recovery of owner fields from our own NodeDB entry if available.
const meshtastic_NodeInfoLite *us = getMeshNode(getNodeNum());
if (nodeInfoLiteHasUser(us)) {
LOG_WARN("Restore owner fields (long_name/short_name/is_licensed/is_unmessagable) from NodeDB for node 0x%08x",
us->num);
// owner.long_name (40) is wider than the lite source (25); bound by the source
memcpy(owner.long_name, us->long_name, sizeof(us->long_name));
owner.long_name[sizeof(us->long_name) - 1] = '\0';
memcpy(owner.short_name, us->short_name, sizeof(owner.short_name));
owner.short_name[sizeof(owner.short_name) - 1] = '\0';
owner.is_licensed = nodeInfoLiteIsLicensed(us);
owner.has_is_unmessagable = nodeInfoLiteHasIsUnmessagable(us);
owner.is_unmessagable = nodeInfoLiteIsUnmessagable(us);

// Save the recovered owner to device state on disk
saveToDisk(SEGMENT_DEVICESTATE);
}
// Deferred until config is loaded: our real NodeNum comes from
// config.security.public_key, which is still unread here.
ownerRecoveryPending = true;
} else {
LOG_INFO("Loaded saved devicestate v%d", devicestate.version);
}
Expand Down Expand Up @@ -2570,6 +2560,32 @@ void NodeDB::loadFromDisk()
saveToDisk(SEGMENT_CONFIG);
}

// config.security is final now, so the key-derived NodeNum is derivable. Matching on
// identity means a nodes.proto without us is a clean miss, not a wrong-owner restore.
if (ownerRecoveryPending) {
// Pre-PKI / keyless builds keep the old behaviour: probe the provisional number.
const NodeNum selfNum = (config.has_security && config.security.public_key.size == 32)
? crc32Buffer(config.security.public_key.bytes, config.security.public_key.size)
: getNodeNum();
const meshtastic_NodeInfoLite *us = getMeshNode(selfNum);
if (nodeInfoLiteHasUser(us)) {
LOG_WARN("Restore owner fields (long_name/short_name/is_licensed/is_unmessagable) from NodeDB for node 0x%08x",
us->num);
// owner.long_name (40) is wider than the lite source (25); bound by the source
memcpy(owner.long_name, us->long_name, sizeof(us->long_name));
owner.long_name[sizeof(us->long_name) - 1] = '\0';
clampLongName(owner.long_name); // recovery now runs past the clamp above; keep the cap invariant
memcpy(owner.short_name, us->short_name, sizeof(owner.short_name));
owner.short_name[sizeof(owner.short_name) - 1] = '\0';
owner.is_licensed = nodeInfoLiteIsLicensed(us);
owner.has_is_unmessagable = nodeInfoLiteHasIsUnmessagable(us);
owner.is_unmessagable = nodeInfoLiteIsUnmessagable(us);

// Save the recovered owner to device state on disk
saveToDisk(SEGMENT_DEVICESTATE);
}
}

// Make sure we load hard coded admin keys even when the configuration file has none.
// Initialize admin_key_count to zero
byte numAdminKeys = 0;
Expand Down