diff --git a/src/chat/chat_service.cpp b/src/chat/chat_service.cpp index 359b14a..0388960 100644 --- a/src/chat/chat_service.cpp +++ b/src/chat/chat_service.cpp @@ -29,8 +29,16 @@ int ChatService::ingest(const std::vector& metadata std::vector* newIncomingCids) { if (!has_identity_) return 0; + const std::string myPubKey = chatIdentityPublicKeyHex(identity_); + int added = 0; for (const auto& meta : metadata) { + // A memo whose sender is our OWN identity is something we sent (only we hold our key). The local + // echo already records it as outgoing — ingesting it as incoming would duplicate it as a phantom + // "from peer" message. (This also collapses same-seed self-chat, where the "peer" wallet shares + // our identity, so every message would otherwise loop back.) + if (!myPubKey.empty() && meta.sender_public_key_hex == myPubKey) continue; + ChatMessage message; message.direction = ChatDirection::Incoming; message.txid = meta.txid; diff --git a/src/services/network_refresh_service.cpp b/src/services/network_refresh_service.cpp index 8d1cf3b..b776b3c 100644 --- a/src/services/network_refresh_service.cpp +++ b/src/services/network_refresh_service.cpp @@ -168,20 +168,6 @@ void appendExtractedHushChatMetadata(std::vector& destination, - const std::string& txid, - const NetworkRefreshService::TransactionViewCacheEntry& entry) -{ - if (!chat::hushChatFeatureEnabledAtBuild()) return; - - std::vector outputs; - outputs.reserve(entry.outgoing_outputs.size()); - for (const auto& output : entry.outgoing_outputs) { - if (!output.memo.empty()) outputs.push_back(chat::HushChatMemoOutput{output.position, output.memo}); - } - appendExtractedHushChatMetadata(destination, txid, outputs); -} - void appendExtractedHushChatMetadata(std::vector& destination, const HushChatMemoOutputMap& outputsByTxid) { @@ -920,7 +906,10 @@ NetworkRefreshService::TransactionRefreshResult NetworkRefreshService::collectTr if (cached != snapshot.viewTxCache.end()) { if (!trackedSend || !cached->second.outgoing_outputs.empty()) { appendViewTransactionOutputs(result.transactions, txid, cached->second); - appendExtractedHushChatMetadata(result.hushChatMetadata, txid, cached->second); + // NB: do NOT extract chat metadata from our OWN outgoing memos here — ingest marks + // everything Incoming, so that duplicates every sent message as a phantom "from peer" + // entry. Genuine incoming comes from the z_listreceivedbyaddress path; our sends are + // recorded by the local echo. (The recent-refresh variant already omits this.) continue; } } @@ -945,7 +934,8 @@ NetworkRefreshService::TransactionRefreshResult NetworkRefreshService::collectTr auto entry = parseViewTransactionCacheEntry(viewTransaction); appendViewTransactionOutputs(result.transactions, txid, entry); - appendExtractedHushChatMetadata(result.hushChatMetadata, txid, entry); + // (Chat metadata is harvested only from RECEIVED notes, not our own outgoing memos — see + // the cached-view branch above.) json rawTransaction; bool hasRawTransaction = false;