Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate transaction status queue for transparent history #1559

Merged
merged 17 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Migrated to Rust 1.80.0.
- `Synchronizer.proposeTransfer` now supports TEX addresses (ZIP 320).
- Internal transactions-enhancing logic has changed to support the history of transactions made to TEX addresses

### Added
- `Synchronizer.isValidTexAddr` which checks whether the given address is a valid ZIP 320 TEX address
Expand Down
52 changes: 33 additions & 19 deletions backend-lib/Cargo.lock

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

20 changes: 9 additions & 11 deletions backend-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ edition = "2018"
rust-version = "1.80"

[dependencies]
orchard = "0.8"
orchard = "0.9"
prost = "0.13"
rusqlite = "0.29"
sapling = { package = "sapling-crypto", version = "0.1", default-features = false }
sapling = { package = "sapling-crypto", version = "0.2", default-features = false }
secrecy = "0.8"
zcash_address = "0.3"
zcash_client_backend = { version = "0.12.1", features = ["orchard", "tor", "transparent-inputs", "unstable"] }
Expand Down Expand Up @@ -67,12 +67,10 @@ path = "src/main/rust/lib.rs"
crate-type = ["staticlib", "cdylib"]

[patch.crates-io]
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "337f59179eda51261e9ddfc6b18e8fb84ea277c9" }
shardtree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "337f59179eda51261e9ddfc6b18e8fb84ea277c9" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "7f7b685b99132505a0fe4ba588f329e3516e9669" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "5a32d3b9bdcb028b4b7522717bceb5afff5112d5" }
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cash.z.ecc.android.sdk.internal.model.JniBlockMeta
import cash.z.ecc.android.sdk.internal.model.JniScanRange
import cash.z.ecc.android.sdk.internal.model.JniScanSummary
import cash.z.ecc.android.sdk.internal.model.JniSubtreeRoot
import cash.z.ecc.android.sdk.internal.model.JniTransactionDataRequest
import cash.z.ecc.android.sdk.internal.model.JniUnifiedSpendingKey
import cash.z.ecc.android.sdk.internal.model.JniWalletSummary
import cash.z.ecc.android.sdk.internal.model.ProposalUnsafe
Expand Down Expand Up @@ -39,7 +40,14 @@ interface Backend {
unifiedSpendingKey: ByteArray
): List<ByteArray>

suspend fun decryptAndStoreTransaction(tx: ByteArray)
/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun decryptAndStoreTransaction(
tx: ByteArray,
minedHeight: Long?
)

/**
* Sets up the internal structure of the data database.
Expand Down Expand Up @@ -176,6 +184,12 @@ interface Backend {
limit: Long
): JniScanSummary

/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun transactionDataRequests(): List<JniTransactionDataRequest>

/**
* @throws RuntimeException as a common indicator of the operation failure
*/
Expand Down Expand Up @@ -206,4 +220,13 @@ interface Backend {
value: Long,
height: Long
)

/**
* @throws RuntimeException as a common indicator of the operation failure
*/
@Throws(RuntimeException::class)
suspend fun setTransactionStatus(
txId: ByteArray,
status: Long,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import cash.z.ecc.android.sdk.internal.model.JniBlockMeta
import cash.z.ecc.android.sdk.internal.model.JniScanRange
import cash.z.ecc.android.sdk.internal.model.JniScanSummary
import cash.z.ecc.android.sdk.internal.model.JniSubtreeRoot
import cash.z.ecc.android.sdk.internal.model.JniTransactionDataRequest
import cash.z.ecc.android.sdk.internal.model.JniUnifiedSpendingKey
import cash.z.ecc.android.sdk.internal.model.JniWalletSummary
import cash.z.ecc.android.sdk.internal.model.ProposalUnsafe
Expand Down Expand Up @@ -295,14 +296,26 @@ class RustBackend private constructor(
}
}

override suspend fun decryptAndStoreTransaction(tx: ByteArray) =
withContext(SdkDispatchers.DATABASE_IO) {
decryptAndStoreTransaction(
dataDbFile.absolutePath,
tx,
override suspend fun transactionDataRequests(): List<JniTransactionDataRequest> {
return withContext(SdkDispatchers.DATABASE_IO) {
transactionDataRequests(
dbDataPath = dataDbFile.absolutePath,
networkId = networkId
)
).asList()
}
}

override suspend fun decryptAndStoreTransaction(
tx: ByteArray,
minedHeight: Long?
) = withContext(SdkDispatchers.DATABASE_IO) {
decryptAndStoreTransaction(
dataDbFile.absolutePath,
tx,
minedHeight = minedHeight ?: -1,
networkId = networkId
)
}

override suspend fun proposeTransfer(
account: Int,
Expand Down Expand Up @@ -382,6 +395,18 @@ class RustBackend private constructor(
)
}

override suspend fun setTransactionStatus(
txId: ByteArray,
status: Long
) = withContext(SdkDispatchers.DATABASE_IO) {
Companion.setTransactionStatus(
dataDbFile.absolutePath,
txId,
status,
networkId = networkId
)
}

override fun isValidSaplingAddr(addr: String) = isValidSaplingAddress(addr, networkId = networkId)

override fun isValidTransparentAddr(addr: String) = isValidTransparentAddress(addr, networkId = networkId)
Expand Down Expand Up @@ -612,10 +637,25 @@ class RustBackend private constructor(
networkId: Int
): JniScanSummary

@JvmStatic
private external fun transactionDataRequests(
dbDataPath: String,
networkId: Int
): Array<JniTransactionDataRequest>

@JvmStatic
private external fun decryptAndStoreTransaction(
dbDataPath: String,
tx: ByteArray,
minedHeight: Long,
networkId: Int
)

@JvmStatic
private external fun setTransactionStatus(
dbDataPath: String,
txId: ByteArray,
status: Long,
networkId: Int
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cash.z.ecc.android.sdk.internal.model

import androidx.annotation.Keep
import cash.z.ecc.android.sdk.internal.ext.isInUIntRange

/**
* Serves as cross layer (Kotlin, Rust) communication class.
*/
@Keep
sealed class JniTransactionDataRequest {
@Keep
class GetStatus(val txid: ByteArray) : JniTransactionDataRequest()

@Keep
class Enhancement(val txid: ByteArray) : JniTransactionDataRequest()

@Keep
data class SpendsFromAddress(
val address: String,
val startHeight: Long,
val endHeight: Long,
) : JniTransactionDataRequest() {
init {
// We require some of the parameters below to be in the range of unsigned integer, because of the Rust layer
// implementation.
require(startHeight.isInUIntRange()) {
"Height $startHeight is outside of allowed UInt range"
}
// We use -1L to represent None across JNI.
if (endHeight != -1L) {
require(endHeight.isInUIntRange()) {
"Height $endHeight is outside of allowed UInt range"
}
require(endHeight >= startHeight) {
"End height $endHeight must be greater than start height $startHeight."
}
}
}
}
}
Loading
Loading