From ad75ed65e5e7b435a92d6d96251cc23529f63c3e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 19 Mar 2024 02:06:08 +0000 Subject: [PATCH 1/2] Correctly throw `InitializeException.SeedRequired` Closes Electric-Coin-Company/zcash-android-wallet-sdk#782. --- CHANGELOG.md | 7 +++++++ .../java/cash/z/ecc/android/sdk/internal/Backend.kt | 4 ++-- .../z/ecc/android/sdk/internal/TypesafeBackend.kt | 4 +++- .../z/ecc/android/sdk/internal/TypesafeBackendImpl.kt | 11 ++++++++++- .../android/sdk/internal/db/derived/DerivedDataDb.kt | 10 +--------- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 324385b6..d06909cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- SDK release 1.11.0-beta01 documented that `Synchronizer.new` would throw an + exception indicating that an internal migration requires the wallet seed, if + called with `null`. This has been unintentionally broken the entire time: the + handling logic for this case was accidentally removed shortly after it was + added. The SDK now correctly throws `InitializeException.SeedRequired`. + ### Changed - The SDK uses ZIP-317 fee system internally - `ZcashSdk.MINERS_FEE` has been deprecated, and will be removed in 2.1.0 diff --git a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt index 0fef4da1..6a59cd39 100644 --- a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt +++ b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt @@ -47,8 +47,8 @@ interface Backend { * * If `seed` is `null`, database migrations will be attempted without it. * - * @return 0 if successful, 1 if the seed must be provided in order to execute the requested migrations, or -1 - * otherwise. + * @return 0 if successful, 1 if the seed must be provided in order to execute the + * requested migrations. * * @throws RuntimeException as a common indicator of the operation failure */ diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt index 42861be8..197f338a 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt @@ -1,5 +1,6 @@ package cash.z.ecc.android.sdk.internal +import cash.z.ecc.android.sdk.exception.InitializeException import cash.z.ecc.android.sdk.internal.model.JniBlockMeta import cash.z.ecc.android.sdk.internal.model.ScanRange import cash.z.ecc.android.sdk.internal.model.ScanSummary @@ -77,7 +78,8 @@ internal interface TypesafeBackend { outputIndex: Int ): String? - suspend fun initDataDb(seed: ByteArray?): Int + @Throws(InitializeException::class) + suspend fun initDataDb(seed: ByteArray?) /** * @throws RuntimeException as a common indicator of the operation failure diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt index 1eb811f3..f3283620 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt @@ -1,5 +1,6 @@ package cash.z.ecc.android.sdk.internal +import cash.z.ecc.android.sdk.exception.InitializeException import cash.z.ecc.android.sdk.internal.model.JniBlockMeta import cash.z.ecc.android.sdk.internal.model.JniSubtreeRoot import cash.z.ecc.android.sdk.internal.model.ScanRange @@ -149,7 +150,15 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke outputIndex: Int ): String? = backend.getMemoAsUtf8(txId, outputIndex) - override suspend fun initDataDb(seed: ByteArray?): Int = backend.initDataDb(seed) + override suspend fun initDataDb(seed: ByteArray?) { + val ret = backend.initDataDb(seed) + when (ret) { + 1 -> throw InitializeException.SeedRequired + 0 -> {} + -1 -> error("Rust backend only uses -1 as an error sentinel") + else -> error("Rust backend used a code that needs to be defined here") + } + } override suspend fun putSaplingSubtreeRoots( startIndex: UInt, diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt index 783e27c0..b35969ee 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt @@ -2,7 +2,6 @@ package cash.z.ecc.android.sdk.internal.db.derived import android.content.Context import androidx.sqlite.db.SupportSQLiteDatabase -import cash.z.ecc.android.sdk.exception.CompactBlockProcessorException import cash.z.ecc.android.sdk.internal.NoBackupContextWrapper import cash.z.ecc.android.sdk.internal.Twig import cash.z.ecc.android.sdk.internal.TypesafeBackend @@ -48,14 +47,7 @@ internal class DerivedDataDb private constructor( numberOfAccounts: Int, recoverUntil: BlockHeight? ): DerivedDataDb { - runCatching { - val result = backend.initDataDb(seed) - if (result < 0) { - throw CompactBlockProcessorException.Uninitialized() - } - }.onFailure { - throw CompactBlockProcessorException.Uninitialized(it) - } + backend.initDataDb(seed) val database = ReadOnlySupportSqliteOpenHelper.openExistingDatabaseAsReadOnly( From 965833ec583015c565f14653bbc6cfe8dd11f1af Mon Sep 17 00:00:00 2001 From: Honza Date: Tue, 19 Mar 2024 17:39:40 +0100 Subject: [PATCH 2/2] Docummentation + unused exception removal --- .../java/cash/z/ecc/android/sdk/exception/Exceptions.kt | 7 ------- .../cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt index 3aaa243a..bbc0a1c8 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt @@ -53,13 +53,6 @@ sealed class CompactBlockProcessorException(message: String, cause: Throwable? = class FailedReorgRepair(message: String) : CompactBlockProcessorException(message) - class Uninitialized(cause: Throwable? = null) : CompactBlockProcessorException( - "Cannot process blocks because the wallet has not been" + - " initialized. Verify that the seed phrase was properly created or imported. If so, then this problem" + - " can be fixed by re-importing the wallet.", - cause - ) - data object NoAccount : CompactBlockProcessorException( "Attempting to scan without an account. This is probably a setup error or a race condition." ) { diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt index f3283620..f5cad61f 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt @@ -154,7 +154,7 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke val ret = backend.initDataDb(seed) when (ret) { 1 -> throw InitializeException.SeedRequired - 0 -> {} + 0 -> { /* Successful case - no action needed */ } -1 -> error("Rust backend only uses -1 as an error sentinel") else -> error("Rust backend used a code that needs to be defined here") }