From 3acbc08f4b47ca6951a6027cd8104fb40ab49593 Mon Sep 17 00:00:00 2001 From: greenart7c3 Date: Wed, 17 Dec 2025 07:35:17 -0300 Subject: [PATCH] Add signer caching to Account model to improve performance - Introduce `signerCache` using a `WeakReference` and a `Mutex` to safely cache the `NostrSignerInternal` instance. - Update `getSigner()` to check the cache before retrieving the encrypted key and creating a new signer. - Add `clearSignerCache()` to explicitly clear the cache on logout. --- .../nostrsigner/LocalPreferences.kt | 1 + .../greenart7c3/nostrsigner/models/Account.kt | 33 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt index fb9095f3..daf77595 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt @@ -363,6 +363,7 @@ object LocalPreferences { */ @SuppressLint("ApplySharedPref") fun updatePrefsForLogout(npub: String, context: Context): Boolean { + accountCache.get(npub)?.clearSignerCache() accountCache.remove(npub) val userPrefs = sharedPrefs(context, npub) userPrefs.edit(commit = true) { clear() } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/Account.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/Account.kt index 1faa9d06..45c8836d 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/models/Account.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/Account.kt @@ -24,11 +24,14 @@ import com.vitorpamplona.quartz.nip49PrivKeyEnc.Nip49 import com.vitorpamplona.quartz.nip55AndroidSigner.signString import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.nip57Zaps.PrivateZapRequestBuilder +import java.lang.ref.WeakReference import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock @Stable class Account( @@ -41,9 +44,30 @@ class Account( ) { val saveable: AccountLiveData = AccountLiveData(this) + @Volatile + private var signerCache: WeakReference? = null + + private val signerMutex = Mutex() + private suspend fun getSigner(): NostrSignerInternal { - val privKey = DataStoreAccess.getEncryptedKey(Amber.instance, npub, DataStoreAccess.NOSTR_PRIVKEY)!! - return NostrSignerInternal(KeyPair(privKey.hexToByteArray())) + signerCache?.get()?.let { return it } + + return signerMutex.withLock { + signerCache?.get()?.let { return it } + + val privKey = DataStoreAccess.getEncryptedKey( + Amber.instance, + npub, + DataStoreAccess.NOSTR_PRIVKEY, + ) ?: throw CancellationException("Signer unavailable") + + val signer = NostrSignerInternal( + KeyPair(privKey.hexToByteArray()), + ) + + signerCache = WeakReference(signer) + signer + } } suspend fun sign(eventTemplate: EventTemplate): T { @@ -138,6 +162,11 @@ class Account( } } } + + fun clearSignerCache() { + signerCache?.clear() + signerCache = null + } } class AccountLiveData(account: Account) : LiveData(AccountState(account))