Migrate to latest Rust revision follow-up changes

This commit is contained in:
Honza 2023-09-06 15:24:27 +02:00
parent 9e334fd375
commit 7b7275b5bd
14 changed files with 81 additions and 38 deletions

View File

@ -38,6 +38,10 @@ interface Backend {
suspend fun initDataDb(seed: ByteArray?): Int
/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun createAccount(seed: ByteArray, treeState: ByteArray, recoverUntil: Long?): JniUnifiedSpendingKey
fun isValidShieldedAddr(addr: String): Boolean
@ -54,6 +58,10 @@ interface Backend {
suspend fun listTransparentReceivers(account: Int): List<String>
/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun getBalance(account: Int): Long
fun getBranchIdForHeight(height: Long): Long
@ -61,8 +69,13 @@ interface Backend {
/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun getMemoAsUtf8(txId: ByteArray, outputIndex: Int): String?
/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun getVerifiedBalance(account: Int): Long
suspend fun getNearestRewindHeight(height: Long): Long

View File

@ -40,5 +40,6 @@ interface Derivation {
companion object {
const val DEFAULT_NUMBER_OF_ACCOUNTS = 1
val DEFAULT_RECOVERY_UNTIL_HEIGHT = null
}
}

View File

@ -239,7 +239,7 @@ class RustBackend private constructor(
)
}
override suspend fun getScanProgress(): JniScanProgress =
override suspend fun getScanProgress(): JniScanProgress? =
withContext(SdkDispatchers.DATABASE_IO) {
getScanProgress(
dataDbFile.absolutePath,
@ -506,7 +506,7 @@ class RustBackend private constructor(
private external fun getScanProgress(
dbDataPath: String,
networkId: Int
): JniScanProgress
): JniScanProgress?
@JvmStatic
private external fun suggestScanRanges(

View File

@ -6,11 +6,22 @@ import androidx.annotation.Keep
* Serves as cross layer (Kotlin, Rust) communication class.
*
* @param numerator the numerator of the progress ratio
* @param endHeight the denominator of the progress ratio
* @param denominator the denominator of the progress ratio
*/
@Keep
class JniScanProgress(
val numerator: Long,
val denominator: Long
) {
init {
require(numerator >= 0L) {
"Numerator $numerator is outside of allowed range [0, Long.MAX_VALUE]"
}
require(denominator >= 1L) {
"Denominator $denominator is outside of allowed range [1, Long.MAX_VALUE]"
}
require(numerator.toFloat().div(denominator) >= 0f) {
"Result of ${numerator.toFloat()}/$denominator is outside of allowed range"
}
}
}

View File

@ -22,7 +22,7 @@ class TreeStateUnsafe(
.setTime(time)
.setSaplingTree(tree)
.build()
return TreeStateUnsafe.new(treeState)
return new(treeState)
}
}
}

View File

@ -2,6 +2,7 @@ package cash.z.ecc.fixture
import cash.z.ecc.android.sdk.internal.Backend
import cash.z.ecc.android.sdk.internal.model.JniBlockMeta
import cash.z.ecc.android.sdk.internal.model.JniScanProgress
import cash.z.ecc.android.sdk.internal.model.JniScanRange
import cash.z.ecc.android.sdk.internal.model.JniSubtreeRoot
import cash.z.ecc.android.sdk.internal.model.JniUnifiedSpendingKey

View File

@ -40,7 +40,6 @@ import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.TransactionOverview
import cash.z.ecc.android.sdk.model.TransactionRecipient
import cash.z.ecc.android.sdk.model.UnifiedFullViewingKey
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
@ -521,8 +520,13 @@ class SdkSynchronizer private constructor(
seed: ByteArray,
checkpoint: Checkpoint,
recoverUntil: BlockHeight?
): UnifiedSpendingKey =
backend.createAccountAndGetSpendingKey(seed, checkpoint, recoverUntil)
): UnifiedSpendingKey? {
return runCatching {
backend.createAccountAndGetSpendingKey(seed, checkpoint, recoverUntil)
}.onFailure {
Twig.error(it) { "Create account failed." }
}.getOrNull()
}
/**
* Returns the current Unified Address for this account.
@ -666,7 +670,8 @@ internal object DefaultSynchronizerFactory {
zcashNetwork: ZcashNetwork,
checkpoint: Checkpoint,
seed: ByteArray?,
numberOfAccounts: Int
numberOfAccounts: Int,
recoverUntil: BlockHeight?
): DerivedDataRepository =
DbDerivedDataRepository(
DerivedDataDb.new(
@ -676,7 +681,8 @@ internal object DefaultSynchronizerFactory {
zcashNetwork,
checkpoint,
seed,
numberOfAccounts
numberOfAccounts,
recoverUntil
)
)

View File

@ -16,7 +16,6 @@ import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.tool.CheckpointTool
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.AddressType
import cash.z.ecc.android.sdk.type.ConsensusMatchType
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
@ -483,7 +482,8 @@ interface Synchronizer {
zcashNetwork,
loadedCheckpoint,
seed,
Derivation.DEFAULT_NUMBER_OF_ACCOUNTS
Derivation.DEFAULT_NUMBER_OF_ACCOUNTS,
Derivation.DEFAULT_RECOVERY_UNTIL_HEIGHT,
)
val service = DefaultSynchronizerFactory.defaultService(applicationContext, lightWalletEndpoint)

View File

@ -2058,18 +2058,20 @@ class CompactBlockProcessor internal constructor(
* @param account the account to check for balance info.
*
* @return an instance of WalletBalance containing information about available and total funds.
*
* @throws RustLayerException.BalanceException if any error occurs while getting the balances via the Rust layer
*/
suspend fun getBalanceInfo(account: Account): WalletBalance {
@Suppress("TooGenericExceptionCaught")
return try {
return runCatching {
val balanceTotal = backend.getBalance(account)
Twig.debug { "found total balance: $balanceTotal" }
Twig.info { "Found total balance: $balanceTotal" }
val balanceAvailable = backend.getVerifiedBalance(account)
Twig.debug { "found available balance: $balanceAvailable" }
Twig.info { "Found available balance: $balanceAvailable" }
WalletBalance(balanceTotal, balanceAvailable)
} catch (t: Throwable) {
Twig.debug { "failed to get balance due to $t" }
throw RustLayerException.BalanceException(t)
}.onFailure {
Twig.error(it) { "Failed to get balance due to ${it.localizedMessage}" }
}.getOrElse {
throw RustLayerException.BalanceException(it)
}
}

View File

@ -8,7 +8,6 @@ import cash.z.ecc.android.sdk.internal.model.SubtreeRoot
import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.UnifiedFullViewingKey
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi

View File

@ -9,12 +9,10 @@ import cash.z.ecc.android.sdk.internal.model.SubtreeRoot
import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.UnifiedFullViewingKey
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.tool.DerivationTool
import kotlinx.coroutines.withContext
@Suppress("TooManyFunctions")

View File

@ -6,9 +6,8 @@ import cash.z.ecc.android.sdk.internal.NoBackupContextWrapper
import cash.z.ecc.android.sdk.internal.Twig
import cash.z.ecc.android.sdk.internal.TypesafeBackend
import cash.z.ecc.android.sdk.internal.db.ReadOnlySupportSqliteOpenHelper
import cash.z.ecc.android.sdk.internal.ext.tryWarn
import cash.z.ecc.android.sdk.internal.model.Checkpoint
import cash.z.ecc.android.sdk.model.UnifiedFullViewingKey
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.ZcashNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -39,7 +38,7 @@ internal class DerivedDataDb private constructor(
// SqliteOpenHelper is happy
private const val DATABASE_VERSION = 8
@Suppress("LongParameterList", "SpreadOperator")
@Suppress("LongParameterList")
suspend fun new(
context: Context,
backend: TypesafeBackend,
@ -47,17 +46,11 @@ internal class DerivedDataDb private constructor(
zcashNetwork: ZcashNetwork,
checkpoint: Checkpoint,
seed: ByteArray?,
numberOfAccounts: Int
numberOfAccounts: Int,
recoverUntil: BlockHeight?
): DerivedDataDb {
backend.initDataDb(seed)
// If a seed is provided, fill in the accounts.
seed?.let {
for (i in 1..numberOfAccounts) {
backend.createAccountAndGetSpendingKey(it, checkpoint, null)
}
}
val database = ReadOnlySupportSqliteOpenHelper.openExistingDatabaseAsReadOnly(
NoBackupContextWrapper(
context,
@ -67,7 +60,25 @@ internal class DerivedDataDb private constructor(
DATABASE_VERSION
)
return DerivedDataDb(zcashNetwork, database)
val dataDb = DerivedDataDb(zcashNetwork, database)
// If a seed is provided, fill in the accounts.
seed?.let { checkedSeed ->
// toInt() should be safe because we expect very few accounts
val missingAccounts = numberOfAccounts - dataDb.accountTable.count().toInt()
require(missingAccounts >= 0) {
"Unexpected number of accounts: $missingAccounts"
}
repeat(missingAccounts) {
runCatching {
backend.createAccountAndGetSpendingKey(checkedSeed, checkpoint, recoverUntil)
}.onFailure {
Twig.error(it) { "Create account failed." }
}
}
}
return dataDb
}
}
}

View File

@ -1,7 +1,7 @@
package cash.z.ecc.android.sdk.internal.model
import cash.z.ecc.android.sdk.internal.ext.isInUIntRange
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.wallet.sdk.internal.rpc.Service.TreeState
import co.electriccoin.lightwallet.client.model.TreeStateUnsafe
/**
@ -21,8 +21,9 @@ internal data class Checkpoint(
val tree: String
) {
fun treeState(): TreeStateUnsafe {
// TODO: epochSeconds should be a Uint32, and for some reason the generated
// Protobuf type Service.TreeState uses Int for this.
require(epochSeconds.isInUIntRange()) {
"epochSeconds $epochSeconds is outside of allowed UInt range"
}
return TreeStateUnsafe.fromParts(height.value, hash, epochSeconds.toInt(), tree)
}

View File

@ -10,7 +10,7 @@ internal data class ScanRange(
override fun toString() = "ScanRange(range=$range, priority=${getSuggestScanRangePriority()})"
internal fun getSuggestScanRangePriority(): SuggestScanRangePriority {
return SuggestScanRangePriority.values()
return SuggestScanRangePriority.entries
.firstOrNull { it.priority == priority } ?: SuggestScanRangePriority.Ignored
}