diff --git a/app/src/main/java/com/bitchat/android/nostr/GeohashMessageHandler.kt b/app/src/main/java/com/bitchat/android/nostr/GeohashMessageHandler.kt index 766169fa..338efd85 100644 --- a/app/src/main/java/com/bitchat/android/nostr/GeohashMessageHandler.kt +++ b/app/src/main/java/com/bitchat/android/nostr/GeohashMessageHandler.kt @@ -78,6 +78,7 @@ class GeohashMessageHandler( if (isTeleportPresence) return@launch val senderName = repo.displayNameForNostrPubkeyUI(event.pubkey) + val hasNonce = try { NostrProofOfWork.hasNonce(event) } catch (_: Exception) { false } val msg = BitchatMessage( id = event.id, sender = senderName, @@ -88,7 +89,9 @@ class GeohashMessageHandler( senderPeerID = "nostr:${event.pubkey.take(8)}", mentions = null, channel = "#$subscribedGeohash", - powDifficulty = try { NostrProofOfWork.calculateDifficulty(event.id).takeIf { it > 0 } } catch (_: Exception) { null } + powDifficulty = try { + if (hasNonce) NostrProofOfWork.calculateDifficulty(event.id).takeIf { it > 0 } else null + } catch (_: Exception) { null } ) withContext(Dispatchers.Main) { messageManager.addChannelMessage("geo:$subscribedGeohash", msg) } } catch (e: Exception) { diff --git a/app/src/main/java/com/bitchat/android/nostr/NostrProofOfWork.kt b/app/src/main/java/com/bitchat/android/nostr/NostrProofOfWork.kt index d713422a..ffbe6607 100644 --- a/app/src/main/java/com/bitchat/android/nostr/NostrProofOfWork.kt +++ b/app/src/main/java/com/bitchat/android/nostr/NostrProofOfWork.kt @@ -54,6 +54,12 @@ object NostrProofOfWork { fun validateDifficulty(event: NostrEvent, minimumDifficulty: Int): Boolean { if (minimumDifficulty <= 0) return true + // Require explicit nonce tag to recognize PoW per NIP-13 intent + if (!hasNonce(event)) { + Log.w(TAG, "Event ${event.id.take(16)}... missing nonce tag; treating as no PoW") + return false + } + val actualDifficulty = calculateDifficulty(event.id) val committedDifficulty = getCommittedDifficulty(event) diff --git a/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt b/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt index 9ecb94f5..6a9e4ee2 100644 --- a/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt @@ -99,14 +99,22 @@ class GeohashViewModel( powDifficulty = if (pow.enabled) pow.difficulty else null ) messageManager.addChannelMessage("geo:${channel.geohash}", localMsg) - if (pow.enabled && pow.difficulty > 0) { + val startedMining = pow.enabled && pow.difficulty > 0 + if (startedMining) { com.bitchat.android.ui.PoWMiningTracker.startMiningMessage(tempId) } - val identity = NostrIdentityBridge.deriveIdentity(forGeohash = channel.geohash, context = getApplication()) - val teleported = state.isTeleported.value ?: false - val event = NostrProtocol.createEphemeralGeohashEvent(content, channel.geohash, identity, nickname, teleported) - val relayManager = NostrRelayManager.getInstance(getApplication()) - relayManager.sendEventToGeohash(event, channel.geohash, includeDefaults = false, nRelays = 5) + try { + val identity = NostrIdentityBridge.deriveIdentity(forGeohash = channel.geohash, context = getApplication()) + val teleported = state.isTeleported.value ?: false + val event = NostrProtocol.createEphemeralGeohashEvent(content, channel.geohash, identity, nickname, teleported) + val relayManager = NostrRelayManager.getInstance(getApplication()) + relayManager.sendEventToGeohash(event, channel.geohash, includeDefaults = false, nRelays = 5) + } finally { + // Ensure we stop the per-message mining animation regardless of success/failure + if (startedMining) { + com.bitchat.android.ui.PoWMiningTracker.stopMiningMessage(tempId) + } + } } catch (e: Exception) { Log.e(TAG, "Failed to send geohash message: ${e.message}") }