From 8f31c273604f38498d69b92c59ec5de2c0add56b Mon Sep 17 00:00:00 2001 From: MarekWo Date: Sat, 7 Mar 2026 07:19:46 +0100 Subject: [PATCH] fix(dm): resolve short pubkey prefix to full key on incoming DM When a DM arrives with only pubkey_prefix (short hex) and the sender is not in mc.contacts, fall back to DB prefix lookup to get the full 64-char public key. Prevents ghost contact entries and "Unknown" DM conversations. Also adds get_contact_by_prefix() database helper. Co-Authored-By: Claude Opus 4.6 --- app/database.py | 9 +++++++++ app/device_manager.py | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/database.py b/app/database.py index e27a3d4..d01e676 100644 --- a/app/database.py +++ b/app/database.py @@ -128,6 +128,15 @@ class Database: ).fetchone() return dict(row) if row else None + def get_contact_by_prefix(self, prefix: str) -> Optional[Dict]: + """Find a contact by public key prefix (LIKE match).""" + with self._connect() as conn: + row = conn.execute( + "SELECT * FROM contacts WHERE public_key LIKE ? AND length(public_key) = 64 LIMIT 1", + (prefix.lower() + '%',) + ).fetchone() + return dict(row) if row else None + def delete_contact(self, public_key: str) -> bool: with self._connect() as conn: cursor = conn.execute( diff --git a/app/device_manager.py b/app/device_manager.py index 53298c3..1018cd1 100644 --- a/app/device_manager.py +++ b/app/device_manager.py @@ -389,10 +389,15 @@ class DeviceManager: contact = self.mc.get_contact_by_key_prefix(sender_key) if contact: sender_name = contact.get('name', '') - # Use the full public key from contacts (not the short prefix) full_key = contact.get('public_key', '') if full_key: sender_key = full_key + elif len(sender_key) < 64: + # Prefix not resolved from in-memory contacts — try DB + db_contact = self.db.get_contact_by_prefix(sender_key) + if db_contact and len(db_contact['public_key']) == 64: + sender_key = db_contact['public_key'] + sender_name = db_contact.get('name', '') # Receiver-side dedup: skip duplicate retries sender_ts = data.get('sender_timestamp')