Skip to content

Commit

Permalink
Switch from ZIP 32 account indices to UUID account identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Nov 22, 2024
1 parent e9a822f commit de385b2
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 173 deletions.
38 changes: 16 additions & 22 deletions backend-lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions backend-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ rayon = "1.7"
# JNI
anyhow = "1"
jni = { version = "0.21", default-features = false }
uuid = "1"

# Logging
log-panics = "2.0.0"
Expand Down Expand Up @@ -69,3 +70,10 @@ xz2 = { version = "0.1", features = ["static"] }
name = "zcashwalletsdk"
path = "src/main/rust/lib.rs"
crate-type = ["staticlib", "cdylib"]

[patch.crates-io]
zcash_address = { git = "https://github.com/zcash/librustzcash", rev = "c8aff5bd06ca7854175234dd88034ff392b36d23" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash", rev = "c8aff5bd06ca7854175234dd88034ff392b36d23" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash", rev = "c8aff5bd06ca7854175234dd88034ff392b36d23" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash", rev = "c8aff5bd06ca7854175234dd88034ff392b36d23" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash", rev = "c8aff5bd06ca7854175234dd88034ff392b36d23" }
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface Backend {
suspend fun initBlockMetaDb(): Int

suspend fun proposeTransfer(
accountIndex: Int,
accountUuid: ByteArray,
to: String,
value: Long,
memo: ByteArray? = null
Expand All @@ -35,12 +35,12 @@ interface Backend {
*/
@Throws(RuntimeException::class)
suspend fun proposeTransferFromUri(
accountIndex: Int,
accountUuid: ByteArray,
uri: String
): ProposalUnsafe

suspend fun proposeShielding(
accountIndex: Int,
accountUuid: ByteArray,
shieldingThreshold: Long,
memo: ByteArray? = null,
transparentReceiver: String? = null
Expand Down Expand Up @@ -109,13 +109,13 @@ interface Backend {
fun isValidTexAddr(addr: String): Boolean

@Throws(RuntimeException::class)
suspend fun getCurrentAddress(accountIndex: Int): String
suspend fun getCurrentAddress(accountUuid: ByteArray): String

fun getTransparentReceiver(ua: String): String?

fun getSaplingReceiver(ua: String): String?

suspend fun listTransparentReceivers(accountIndex: Int): List<String>
suspend fun listTransparentReceivers(accountUuid: ByteArray): List<String>

fun getBranchIdForHeight(height: Long): Long

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ class RustBackend private constructor(
)
}

override suspend fun getCurrentAddress(accountIndex: Int) =
override suspend fun getCurrentAddress(accountUuid: ByteArray) =
withContext(SdkDispatchers.DATABASE_IO) {
getCurrentAddress(
dataDbFile.absolutePath,
accountIndex,
accountUuid,
networkId = networkId
)
}
Expand All @@ -127,11 +127,11 @@ class RustBackend private constructor(

override fun getSaplingReceiver(ua: String) = getSaplingReceiverForUnifiedAddress(ua)

override suspend fun listTransparentReceivers(accountIndex: Int): List<String> {
override suspend fun listTransparentReceivers(accountUuid: ByteArray): List<String> {
return withContext(SdkDispatchers.DATABASE_IO) {
listTransparentReceivers(
dbDataPath = dataDbFile.absolutePath,
accountIndex = accountIndex,
accountUuid = accountUuid,
networkId = networkId
).asList()
}
Expand Down Expand Up @@ -318,22 +318,22 @@ class RustBackend private constructor(
}

override suspend fun proposeTransferFromUri(
accountIndex: Int,
accountUuid: ByteArray,
uri: String
): ProposalUnsafe =
withContext(SdkDispatchers.DATABASE_IO) {
ProposalUnsafe.parse(
proposeTransferFromUri(
dataDbFile.absolutePath,
accountIndex,
accountUuid,
uri,
networkId = networkId,
)
)
}

override suspend fun proposeTransfer(
accountIndex: Int,
accountUuid: ByteArray,
to: String,
value: Long,
memo: ByteArray?
Expand All @@ -342,7 +342,7 @@ class RustBackend private constructor(
ProposalUnsafe.parse(
proposeTransfer(
dataDbFile.absolutePath,
accountIndex,
accountUuid,
to,
value,
memo,
Expand All @@ -352,15 +352,15 @@ class RustBackend private constructor(
}

override suspend fun proposeShielding(
accountIndex: Int,
accountUuid: ByteArray,
shieldingThreshold: Long,
memo: ByteArray?,
transparentReceiver: String?
): ProposalUnsafe? {
return withContext(SdkDispatchers.DATABASE_IO) {
proposeShielding(
dataDbFile.absolutePath,
accountIndex,
accountUuid,
shieldingThreshold,
memo,
transparentReceiver,
Expand Down Expand Up @@ -510,7 +510,7 @@ class RustBackend private constructor(
@JvmStatic
private external fun getCurrentAddress(
dbDataPath: String,
accountIndex: Int,
accountUuid: ByteArray,
networkId: Int
): String

Expand All @@ -523,7 +523,7 @@ class RustBackend private constructor(
@JvmStatic
private external fun listTransparentReceivers(
dbDataPath: String,
accountIndex: Int,
accountUuid: ByteArray,
networkId: Int
): Array<String>

Expand Down Expand Up @@ -671,7 +671,7 @@ class RustBackend private constructor(
@JvmStatic
private external fun proposeTransferFromUri(
dbDataPath: String,
accountIndex: Int,
accountUuid: ByteArray,
uri: String,
networkId: Int,
): ByteArray
Expand All @@ -680,7 +680,7 @@ class RustBackend private constructor(
@Suppress("LongParameterList")
private external fun proposeTransfer(
dbDataPath: String,
accountIndex: Int,
accountUuid: ByteArray,
to: String,
value: Long,
memo: ByteArray?,
Expand All @@ -691,7 +691,7 @@ class RustBackend private constructor(
@Suppress("LongParameterList")
private external fun proposeShielding(
dbDataPath: String,
accountIndex: Int,
accountUuid: ByteArray,
shieldingThreshold: Long,
memo: ByteArray?,
transparentReceiver: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ import androidx.annotation.Keep
/**
* Serves as cross layer (Kotlin, Rust) communication class.
*
* @param accountIndex the ZIP 32 account index.
* @param accountUuid the "one-way stable" identifier for the account.
* @param ufvk The account's Unified Full Viewing Key, if any.
* @throws IllegalArgumentException if the values are inconsistent.
*/
@Keep
@Suppress("LongParameterList")
class JniAccount(
val accountIndex: Int,
val accountUuid: ByteArray,
val ufvk: String?,
) {
init {
require(accountIndex >= 0) {
"Account index must be non-negative"
require(accountUuid.size == 16) {
"Account UUID must be 16 bytes"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import androidx.annotation.Keep
@Keep
@Suppress("LongParameterList")
class JniAccountBalance(
val account: Int,
val account: ByteArray,
val saplingVerifiedBalance: Long,
val saplingChangePending: Long,
val saplingValuePending: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import androidx.annotation.Keep
@Keep
class JniUnifiedSpendingKey(
/**
* The [ZIP 32](https://zips.z.cash/zip-0032) account index used to derive this key.
* The "one-way stable" identifier for the account tracked in the wallet to which this
* spending key belongs.
*/
val account: Int,
val accountUuid: ByteArray,
/**
* The binary encoding of the [ZIP 316](https://zips.z.cash/zip-0316) Unified Spending
* Key for [account].
* Key for [accountUuid].
*
* This encoding **MUST NOT** be exposed to users. It is an internal encoding that is
* inherently unstable, and only intended to be passed between the SDK and the storage
Expand All @@ -28,22 +29,22 @@ class JniUnifiedSpendingKey(
val bytes: ByteArray
) {
// Override to prevent leaking key to logs
override fun toString() = "JniUnifiedSpendingKey(account=$account, bytes=***)"
override fun toString() = "JniUnifiedSpendingKey(account=$accountUuid, bytes=***)"

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as JniUnifiedSpendingKey

if (account != other.account) return false
if (!accountUuid.contentEquals(other.accountUuid)) return false
if (!bytes.contentEquals(other.bytes)) return false

return true
}

override fun hashCode(): Int {
var result = account.hashCode()
var result = accountUuid.hashCode()
result = 31 * result + bytes.hashCode()
return result
}
Expand Down
Loading

0 comments on commit de385b2

Please sign in to comment.