TMM & Warmstore key source naming (#11119)

* one becomes two

* warmstore clarify

* Address PR review: key-provenance terminology consistency

- Log line now says "not key-proven" (gate is XEdDSA OR manual, not just signer)
- Rename markKeySignerProvenForTest -> markKeyXeddsaSignedForTest (sets only the XEdDSA bit)
- Docs + test comments: "signer bit" -> "XEdDSA-signed bit"

clod helped too

* Rename signer-proven -> key-proven for broadened provenance predicate

Address PR #11119 review: the copyPublicKey()/copyUser() out-parameter and
the cache-path replay gate now report entry->keyProven() (XEdDSA-signed OR
manually verified), so the "signerProven" name and "signer-proven" comments
were misleading. Rename the public out-param to keyProven, the local
cachedKeySignerProven to cachedKeyProven, and update coupled callers, log
strings, docs headings, and comments to say "key-proven".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* nitpicks

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom
2026-07-31 10:39:39 +00:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 6367132919
commit e26b6bfc5a
11 changed files with 314 additions and 189 deletions
+9 -9
View File
@@ -3974,7 +3974,7 @@ bool NodeDB::copyPublicKey(NodeNum n, meshtastic_NodeInfoLite_public_key_t &out)
#if HAS_TRAFFIC_MANAGEMENT
// Last resort: a key the TrafficManagement NodeInfo cache learned from an observed frame
// for a node no longer in either NodeDB tier. This extends the pool of peers we can
// encrypt to. Keys here may be trust-on-first-use (see copyPublicKey's signerProven), the
// encrypt to. Keys here may be trust-on-first-use (see copyPublicKey's keyProven), the
// same first-contact trust NodeDB itself applies via updateUser().
if (trafficManagementModule && trafficManagementModule->copyPublicKey(n, out.bytes)) {
out.size = 32;
@@ -3989,10 +3989,10 @@ bool NodeDB::copyPublicKeyForDecrypt(NodeNum n, meshtastic_NodeInfoLite_public_k
if (copyPublicKeyAuthoritative(n, out))
return true;
#if HAS_TRAFFIC_MANAGEMENT
// A cold-tier cache key backs an authenticated decrypt only when signer-proven; unverified TOFU
// A cold-tier cache key backs an authenticated decrypt only when key-proven; unverified TOFU
// cache keys must not. Outbound encryption still uses the opportunistic copyPublicKey().
bool signerProven = false;
if (trafficManagementModule && trafficManagementModule->copyPublicKey(n, out.bytes, &signerProven) && signerProven) {
bool keyProven = false;
if (trafficManagementModule && trafficManagementModule->copyPublicKey(n, out.bytes, &keyProven) && keyProven) {
out.size = 32;
return true;
}
@@ -4012,7 +4012,7 @@ bool NodeDB::isVerifiedSignerForKey(NodeNum n, const uint8_t *key32)
#if WARM_NODE_COUNT > 0
uint8_t warmKey[32];
if (warmStore.copyKey(n, warmKey) && memcmp(warmKey, key32, 32) == 0)
return warmStore.isVerifiedSigner(n);
return warmStore.hasXeddsaSigned(n);
#endif
return false;
}
@@ -4024,7 +4024,7 @@ bool NodeDB::isKnownXeddsaSigner(NodeNum n)
if (info)
return nodeInfoLiteHasXeddsaSigned(info);
#if WARM_NODE_COUNT > 0
return warmStore.isVerifiedSigner(n);
return warmStore.hasXeddsaSigned(n);
#else
return false;
#endif
@@ -4146,9 +4146,9 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
// Restore the role the warm tier cached, so re-admission isn't stuck at CLIENT
// until the next NodeInfo arrives.
lite->role = static_cast<meshtastic_Config_DeviceConfig_Role>(warmRoleOf(warm));
// Restore the signer bit too: it is learned from verified traffic, not from
// Restore the XEdDSA-signed bit too: it is learned from verified traffic, not from
// NodeInfo, so a round trip through the warm tier must not relearn it from zero.
nodeInfoLiteSetBit(lite, NODEINFO_BITFIELD_HAS_XEDDSA_SIGNED_MASK, warmSignerOf(warm));
nodeInfoLiteSetBit(lite, NODEINFO_BITFIELD_HAS_XEDDSA_SIGNED_MASK, warmXeddsaSignedOf(warm));
if (!memfll(warm.public_key, 0, sizeof(warm.public_key))) {
lite->public_key.size = 32;
memcpy(lite->public_key.bytes, warm.public_key, 32);
@@ -4165,7 +4165,7 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
// its cached key matches the key we just restored from warm, so a name never attaches to
// a different identity than the one we encrypt to. No-op without the TMM NodeInfo cache
// or when no key is present (key-matched by design). CopyUserToNodeInfoLite sets only the
// user-related bits, so the warm-restored signer bit survives.
// user-related bits, so the warm-restored XEdDSA-signed bit survives.
if (lite->public_key.size == 32 && !nodeInfoLiteHasUser(lite) && trafficManagementModule) {
meshtastic_User tmmUser = meshtastic_User_init_zero;
if (trafficManagementModule->copyUser(n, tmmUser) && tmmUser.public_key.size == 32 &&