mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 00:25:19 +00:00
Apply PoW to geohash system/raw sends\n\n- Use same mining/signing path for screenshot and sendPublicRaw in geohash\n- Factor helper mineAndSendGeohashEvent(...) in ChatViewModel
This commit is contained in:
@@ -7,11 +7,11 @@ enum PowPolicy {
|
||||
/// Clamped to a sane range to keep UX responsive on phones.
|
||||
static func requiredBits(forGeohash geohash: String) -> Int {
|
||||
let precision = geohash.count
|
||||
// Start at 16 and go down with higher precision (smaller areas)
|
||||
// Start at 13 and go down with higher precision (smaller areas)
|
||||
switch precision {
|
||||
case ...5: return 10
|
||||
case 6: return 9
|
||||
default: return 8
|
||||
case ...5: return 13
|
||||
case 6: return 12
|
||||
default: return 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,27 +2786,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
meshService.sendMessage(screenshotMessage, mentions: [])
|
||||
case .location(let ch):
|
||||
Task { @MainActor in
|
||||
do {
|
||||
let identity = try NostrIdentityBridge.deriveIdentity(forGeohash: ch.geohash)
|
||||
let event = try NostrProtocol.createEphemeralGeohashEvent(
|
||||
content: screenshotMessage,
|
||||
geohash: ch.geohash,
|
||||
senderIdentity: identity,
|
||||
nickname: self.nickname,
|
||||
teleported: LocationChannelManager.shared.teleported
|
||||
)
|
||||
let targetRelays = GeoRelayDirectory.shared.closestRelays(toGeohash: ch.geohash, count: 5)
|
||||
if targetRelays.isEmpty {
|
||||
SecureLogger.log("Geo: no geohash relays available for \(ch.geohash); not sending", category: SecureLogger.session, level: .warning)
|
||||
} else {
|
||||
NostrRelayManager.shared.sendEvent(event, to: targetRelays)
|
||||
}
|
||||
// Track ourselves as active participant
|
||||
self.recordGeoParticipant(pubkeyHex: identity.publicKeyHex)
|
||||
} catch {
|
||||
SecureLogger.log("❌ Failed to send geohash screenshot message: \(error)", category: SecureLogger.session, level: .error)
|
||||
self.addSystemMessage("failed to send to location channel")
|
||||
}
|
||||
await mineAndSendGeohashEvent(content: screenshotMessage, geohash: ch.geohash, nickname: self.nickname, teleported: LocationChannelManager.shared.teleported, createdAt: Date())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5058,30 +5038,56 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
func sendPublicRaw(_ content: String) {
|
||||
if case .location(let ch) = activeChannel {
|
||||
Task { @MainActor in
|
||||
do {
|
||||
let identity = try NostrIdentityBridge.deriveIdentity(forGeohash: ch.geohash)
|
||||
let event = try NostrProtocol.createEphemeralGeohashEvent(
|
||||
content: content,
|
||||
geohash: ch.geohash,
|
||||
senderIdentity: identity,
|
||||
nickname: self.nickname,
|
||||
teleported: LocationChannelManager.shared.teleported
|
||||
)
|
||||
let targetRelays = GeoRelayDirectory.shared.closestRelays(toGeohash: ch.geohash, count: 5)
|
||||
if targetRelays.isEmpty {
|
||||
NostrRelayManager.shared.sendEvent(event)
|
||||
} else {
|
||||
NostrRelayManager.shared.sendEvent(event, to: targetRelays)
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.log("❌ Failed to send geohash raw message: \(error)", category: SecureLogger.session, level: .error)
|
||||
}
|
||||
await mineAndSendGeohashEvent(content: content, geohash: ch.geohash, nickname: self.nickname, teleported: LocationChannelManager.shared.teleported, createdAt: Date())
|
||||
}
|
||||
return
|
||||
}
|
||||
// Default: send over mesh
|
||||
meshService.sendMessage(content, mentions: [])
|
||||
}
|
||||
|
||||
// MARK: - Geohash PoW helper for system/raw messages
|
||||
@MainActor
|
||||
private func mineAndSendGeohashEvent(content: String, geohash: String, nickname: String, teleported: Bool, createdAt: Date) async {
|
||||
do {
|
||||
let identity = try NostrIdentityBridge.deriveIdentity(forGeohash: geohash)
|
||||
let createdAtSecs = Int(createdAt.timeIntervalSince1970)
|
||||
var baseTags = [["g", geohash]]
|
||||
if !nickname.isEmpty { baseTags.append(["n", nickname]) }
|
||||
if teleported { baseTags.append(["t", "teleport"]) }
|
||||
let bits = PowPolicy.requiredBits(forGeohash: geohash)
|
||||
let (nonce, _) = await withCheckedContinuation { (cont: CheckedContinuation<(UInt64, String), Never>) in
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
let res = NostrPoW.mine(pubkey: identity.publicKeyHex,
|
||||
createdAt: createdAtSecs,
|
||||
kind: NostrProtocol.EventKind.ephemeralEvent.rawValue,
|
||||
baseTags: baseTags,
|
||||
content: content,
|
||||
targetBits: bits)
|
||||
cont.resume(returning: (res.nonce, res.idHex))
|
||||
}
|
||||
}
|
||||
var tags = baseTags
|
||||
tags.append(["nonce", String(nonce), String(bits)])
|
||||
var event = NostrEvent(
|
||||
pubkey: identity.publicKeyHex,
|
||||
createdAt: createdAt,
|
||||
kind: .ephemeralEvent,
|
||||
tags: tags,
|
||||
content: content
|
||||
)
|
||||
let key = try identity.schnorrSigningKey()
|
||||
event = try event.sign(with: key)
|
||||
let relays = GeoRelayDirectory.shared.closestRelays(toGeohash: geohash, count: TransportConfig.nostrGeoRelayCount)
|
||||
if relays.isEmpty {
|
||||
NostrRelayManager.shared.sendEvent(event)
|
||||
} else {
|
||||
NostrRelayManager.shared.sendEvent(event, to: relays)
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.log("❌ GeoPoW: failed to send event: \(error)", category: SecureLogger.session, level: .error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Simplified Nostr Integration (Inlined from MessageRouter)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user