refactor(desktop): move DM peer crypto off the main thread

The nip44_encrypt_to_peer / nip44_decrypt_from_peer commands ran the
CPU-bound NIP-44 encrypt/decrypt synchronously while holding the keys
lock on the main thread. #1222 already moved the equivalent *_self
commands off-thread via async + spawn_blocking; these DM commands
predate that change and were left on the asymmetric path. Mirror the
*_self template so the hottest DM paths (encrypt-on-send,
decrypt-on-render) no longer block the main thread. Callers are
unchanged — both already await through invokeTauri.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
Will Pfleger
2026-06-25 17:55:44 -04:00
parent 6604d5882e
commit 752bb5019e
+18 -8
View File
@@ -274,16 +274,21 @@ pub async fn nip44_decrypt_from_self(
/// Rust backend — the frontend only sends plaintext + peer pubkey and gets the
/// ciphertext back to embed in the kind:9 it signs. Used for DM encrypt-on-send.
#[tauri::command]
pub fn nip44_encrypt_to_peer(
pub async fn nip44_encrypt_to_peer(
peer_pubkey: String,
plaintext: String,
state: State<'_, AppState>,
) -> Result<String, String> {
let peer =
PublicKey::from_hex(peer_pubkey.trim()).map_err(|e| format!("invalid peer pubkey: {e}"))?;
let keys = state.keys.lock().map_err(|e| e.to_string())?;
nip44::encrypt(keys.secret_key(), &peer, &plaintext, nip44::Version::V2)
.map_err(|e| format!("nip44 encrypt failed: {e}"))
let keys = state.keys.lock().map_err(|e| e.to_string())?.clone();
tauri::async_runtime::spawn_blocking(move || {
nip44::encrypt(keys.secret_key(), &peer, &plaintext, nip44::Version::V2)
.map_err(|e| format!("nip44 encrypt failed: {e}"))
})
.await
.map_err(|e| format!("spawn_blocking failed: {e}"))?
}
/// NIP-44 v2 decrypt DM `ciphertext` from a peer. The peer pubkey is the other
@@ -292,14 +297,19 @@ pub fn nip44_encrypt_to_peer(
/// key decrypts both). Used for DM decrypt-on-render; on failure the frontend
/// shows the mixed-version placeholder rather than blank or garbled content.
#[tauri::command]
pub fn nip44_decrypt_from_peer(
pub async fn nip44_decrypt_from_peer(
peer_pubkey: String,
ciphertext: String,
state: State<'_, AppState>,
) -> Result<String, String> {
let peer =
PublicKey::from_hex(peer_pubkey.trim()).map_err(|e| format!("invalid peer pubkey: {e}"))?;
let keys = state.keys.lock().map_err(|e| e.to_string())?;
nip44::decrypt(keys.secret_key(), &peer, &ciphertext)
.map_err(|e| format!("nip44 decrypt failed: {e}"))
let keys = state.keys.lock().map_err(|e| e.to_string())?.clone();
tauri::async_runtime::spawn_blocking(move || {
nip44::decrypt(keys.secret_key(), &peer, &ciphertext)
.map_err(|e| format!("nip44 decrypt failed: {e}"))
})
.await
.map_err(|e| format!("spawn_blocking failed: {e}"))?
}