mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 16:45: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.
|
/// Clamped to a sane range to keep UX responsive on phones.
|
||||||
static func requiredBits(forGeohash geohash: String) -> Int {
|
static func requiredBits(forGeohash geohash: String) -> Int {
|
||||||
let precision = geohash.count
|
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 {
|
switch precision {
|
||||||
case ...5: return 10
|
case ...5: return 13
|
||||||
case 6: return 9
|
case 6: return 12
|
||||||
default: return 8
|
default: return 11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2786,27 +2786,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
meshService.sendMessage(screenshotMessage, mentions: [])
|
meshService.sendMessage(screenshotMessage, mentions: [])
|
||||||
case .location(let ch):
|
case .location(let ch):
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
do {
|
await mineAndSendGeohashEvent(content: screenshotMessage, geohash: ch.geohash, nickname: self.nickname, teleported: LocationChannelManager.shared.teleported, createdAt: Date())
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5058,24 +5038,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
func sendPublicRaw(_ content: String) {
|
func sendPublicRaw(_ content: String) {
|
||||||
if case .location(let ch) = activeChannel {
|
if case .location(let ch) = activeChannel {
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
do {
|
await mineAndSendGeohashEvent(content: content, geohash: ch.geohash, nickname: self.nickname, teleported: LocationChannelManager.shared.teleported, createdAt: Date())
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -5083,6 +5046,49 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
meshService.sendMessage(content, mentions: [])
|
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)
|
// MARK: - Simplified Nostr Integration (Inlined from MessageRouter)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user