Rename JniConverter to RustBackend
Turns out JNI classes are hard to mock due to the way sytem libraries are loaded. So it became easier to put the JniConverter class behind an interface. Once that refactor was necessary, it was a good time to update the name of this class because it retained its original PoC name for far too long.
This commit is contained in:
parent
4948617d6d
commit
c3f57d5e2f
|
@ -2,7 +2,7 @@ package cash.z.wallet.sdk.sample.memo
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import cash.z.wallet.sdk.data.*
|
import cash.z.wallet.sdk.data.*
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
import cash.z.wallet.sdk.jni.RustBackend
|
||||||
import cash.z.wallet.sdk.secure.Wallet
|
import cash.z.wallet.sdk.secure.Wallet
|
||||||
|
|
||||||
object Injection {
|
object Injection {
|
||||||
|
@ -15,7 +15,7 @@ object Injection {
|
||||||
val downloader = CompactBlockStream(host, port)
|
val downloader = CompactBlockStream(host, port)
|
||||||
val wallet = Wallet(
|
val wallet = Wallet(
|
||||||
context = appContext,
|
context = appContext,
|
||||||
converter = JniConverter(),
|
rustBackend = RustBackend(),
|
||||||
dataDbPath = appContext.getDatabasePath(dataDbName).absolutePath,
|
dataDbPath = appContext.getDatabasePath(dataDbName).absolutePath,
|
||||||
paramDestinationDir = "${appContext.cacheDir.absolutePath}/params",
|
paramDestinationDir = "${appContext.cacheDir.absolutePath}/params",
|
||||||
seedProvider = SampleSeedProvider("testreferencealice"),
|
seedProvider = SampleSeedProvider("testreferencealice"),
|
||||||
|
|
|
@ -10,8 +10,9 @@ import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||||
import cash.z.wallet.sdk.dao.TransactionDao
|
import cash.z.wallet.sdk.dao.TransactionDao
|
||||||
import cash.z.wallet.sdk.data.SampleSeedProvider
|
import cash.z.wallet.sdk.data.SampleSeedProvider
|
||||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
import cash.z.wallet.sdk.jni.RustBackend
|
||||||
import cash.z.wallet.sdk.entity.CompactBlock
|
import cash.z.wallet.sdk.entity.CompactBlock
|
||||||
|
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||||
import io.grpc.ManagedChannel
|
import io.grpc.ManagedChannel
|
||||||
import io.grpc.ManagedChannelBuilder
|
import io.grpc.ManagedChannelBuilder
|
||||||
import org.junit.*
|
import org.junit.*
|
||||||
|
@ -55,12 +56,12 @@ class GlueIntegrationTest {
|
||||||
|
|
||||||
private fun scanData() {
|
private fun scanData() {
|
||||||
val dbFileName = "/data/user/0/cash.z.wallet.sdk.test/databases/new-data-glue.db"
|
val dbFileName = "/data/user/0/cash.z.wallet.sdk.test/databases/new-data-glue.db"
|
||||||
converter.initDataDb(dbFileName)
|
rustBackend.initDataDb(dbFileName)
|
||||||
converter.initAccountsTable(dbFileName, "dummyseed".toByteArray(), 1)
|
rustBackend.initAccountsTable(dbFileName, "dummyseed".toByteArray(), 1)
|
||||||
|
|
||||||
|
|
||||||
Log.e("tezt", "scanning blocks...")
|
Log.e("tezt", "scanning blocks...")
|
||||||
val result = converter.scanBlocks(cacheDbPath, dbFileName)
|
val result = rustBackend.scanBlocks(cacheDbPath, dbFileName)
|
||||||
System.err.println("done.")
|
System.err.println("done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ class GlueIntegrationTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// jni
|
// jni
|
||||||
val converter: JniConverter = JniConverter()
|
val rustBackend: RustBackendWelding = RustBackend()
|
||||||
|
|
||||||
// db
|
// db
|
||||||
private lateinit var dao: CompactBlockDao
|
private lateinit var dao: CompactBlockDao
|
||||||
|
@ -84,7 +85,7 @@ class GlueIntegrationTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setup() {
|
fun setup() {
|
||||||
converter.initLogs()
|
rustBackend.initLogs()
|
||||||
|
|
||||||
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
||||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||||
|
|
|
@ -8,9 +8,10 @@ import androidx.test.core.app.ApplicationProvider
|
||||||
import cash.z.wallet.sdk.dao.BlockDao
|
import cash.z.wallet.sdk.dao.BlockDao
|
||||||
import cash.z.wallet.sdk.dao.CompactBlockDao
|
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||||
import cash.z.wallet.sdk.dao.TransactionDao
|
import cash.z.wallet.sdk.dao.TransactionDao
|
||||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
|
||||||
import cash.z.wallet.sdk.entity.CompactBlock
|
import cash.z.wallet.sdk.entity.CompactBlock
|
||||||
|
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||||
|
import cash.z.wallet.sdk.jni.RustBackend
|
||||||
|
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||||
import io.grpc.ManagedChannel
|
import io.grpc.ManagedChannel
|
||||||
import io.grpc.ManagedChannelBuilder
|
import io.grpc.ManagedChannelBuilder
|
||||||
import org.junit.*
|
import org.junit.*
|
||||||
|
@ -55,7 +56,7 @@ class GlueSetupIntegrationTest {
|
||||||
|
|
||||||
private fun scanData() {
|
private fun scanData() {
|
||||||
Log.e("tezt", "scanning blocks...")
|
Log.e("tezt", "scanning blocks...")
|
||||||
val result = converter.scanBlocks(cacheDbPath, "/data/user/0/cash.z.wallet.sdk.test/databases/data-glue.db")
|
val result = rustBackend.scanBlocks(cacheDbPath, "/data/user/0/cash.z.wallet.sdk.test/databases/data-glue.db")
|
||||||
System.err.println("done.")
|
System.err.println("done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ class GlueSetupIntegrationTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// jni
|
// jni
|
||||||
val converter: JniConverter = JniConverter()
|
val rustBackend: RustBackendWelding = RustBackend()
|
||||||
|
|
||||||
// db
|
// db
|
||||||
private lateinit var dao: CompactBlockDao
|
private lateinit var dao: CompactBlockDao
|
||||||
|
@ -79,7 +80,7 @@ class GlueSetupIntegrationTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setup() {
|
fun setup() {
|
||||||
converter.initLogs()
|
rustBackend.initLogs()
|
||||||
|
|
||||||
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
||||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cash.z.wallet.sdk.db
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import cash.z.wallet.sdk.data.*
|
import cash.z.wallet.sdk.data.*
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
import cash.z.wallet.sdk.jni.RustBackend
|
||||||
import cash.z.wallet.sdk.secure.Wallet
|
import cash.z.wallet.sdk.secure.Wallet
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.AfterClass
|
import org.junit.AfterClass
|
||||||
|
@ -40,16 +40,16 @@ class IntegrationTest {
|
||||||
|
|
||||||
@Test(timeout = 1L * DateUtils.MINUTE_IN_MILLIS/10)
|
@Test(timeout = 1L * DateUtils.MINUTE_IN_MILLIS/10)
|
||||||
fun testSync() = runBlocking<Unit> {
|
fun testSync() = runBlocking<Unit> {
|
||||||
val converter = JniConverter()
|
val rustBackend = RustBackend()
|
||||||
converter.initLogs()
|
rustBackend.initLogs()
|
||||||
val logger = TroubleshootingTwig()
|
val logger = TroubleshootingTwig()
|
||||||
|
|
||||||
downloader = CompactBlockStream("10.0.2.2", 9067, logger)
|
downloader = CompactBlockStream("10.0.2.2", 9067, logger)
|
||||||
processor = CompactBlockProcessor(context, converter, cacheDdName, dataDbName, logger = logger)
|
processor = CompactBlockProcessor(context, rustBackend, cacheDdName, dataDbName, logger = logger)
|
||||||
repository = PollingTransactionRepository(context, dataDbName, 10_000L)
|
repository = PollingTransactionRepository(context, dataDbName, 10_000L)
|
||||||
wallet = Wallet(
|
wallet = Wallet(
|
||||||
context,
|
context,
|
||||||
converter,
|
rustBackend,
|
||||||
context.getDatabasePath(dataDbName).absolutePath,
|
context.getDatabasePath(dataDbName).absolutePath,
|
||||||
context.cacheDir.absolutePath,
|
context.cacheDir.absolutePath,
|
||||||
arrayOf(0),
|
arrayOf(0),
|
||||||
|
|
|
@ -6,29 +6,29 @@ import org.junit.Assert.assertNotNull
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class JniConverterTest {
|
class RustBackendTest {
|
||||||
|
|
||||||
private val dbDataFile = "/data/user/0/cash.z.wallet.sdk.test/databases/data2.db"
|
private val dbDataFile = "/data/user/0/cash.z.wallet.sdk.test/databases/data2.db"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetAddress_exists() {
|
fun testGetAddress_exists() {
|
||||||
assertNotNull(converter.getAddress(dbDataFile, 0))
|
assertNotNull(rustBackend.getAddress(dbDataFile, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetAddress_valid() {
|
fun testGetAddress_valid() {
|
||||||
val address = converter.getAddress(dbDataFile, 0)
|
val address = rustBackend.getAddress(dbDataFile, 0)
|
||||||
val expectedAddress = "ztestsapling1snmqdnfqnc407pvqw7sld8w5zxx6nd0523kvlj4jf39uvxvh7vn0hs3q38n07806dwwecqwke3t"
|
val expectedAddress = "ztestsapling1snmqdnfqnc407pvqw7sld8w5zxx6nd0523kvlj4jf39uvxvh7vn0hs3q38n07806dwwecqwke3t"
|
||||||
assertEquals("Invalid address", expectedAddress, address)
|
assertEquals("Invalid address", expectedAddress, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testScanBlocks() {
|
fun testScanBlocks() {
|
||||||
converter.initDataDb(dbDataFile)
|
rustBackend.initDataDb(dbDataFile)
|
||||||
converter.initAccountsTable(dbDataFile, "dummyseed".toByteArray(), 1)
|
rustBackend.initAccountsTable(dbDataFile, "dummyseed".toByteArray(), 1)
|
||||||
|
|
||||||
// note: for this to work, the db file below must be uploaded to the device. Eventually, this test will be self-contained and remove that requirement.
|
// note: for this to work, the db file below must be uploaded to the device. Eventually, this test will be self-contained and remove that requirement.
|
||||||
val result = converter.scanBlocks(
|
val result = rustBackend.scanBlocks(
|
||||||
"/data/user/0/cash.z.wallet.sdk.test/databases/dummy-cache.db",
|
"/data/user/0/cash.z.wallet.sdk.test/databases/dummy-cache.db",
|
||||||
dbDataFile
|
dbDataFile
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ class JniConverterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSend() {
|
fun testSend() {
|
||||||
converter.sendToAddress(
|
rustBackend.sendToAddress(
|
||||||
"/data/user/0/cash.z.wallet.sdk.test/databases/data2.db",
|
"/data/user/0/cash.z.wallet.sdk.test/databases/data2.db",
|
||||||
0,
|
0,
|
||||||
"dummykey",
|
"dummykey",
|
||||||
|
@ -51,12 +51,12 @@ class JniConverterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val converter: JniConverter = JniConverter()
|
val rustBackend: RustBackendWelding = RustBackend()
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setup() {
|
fun setup() {
|
||||||
converter.initLogs()
|
rustBackend.initLogs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ import androidx.room.RoomDatabase
|
||||||
import cash.z.wallet.sdk.dao.CompactBlockDao
|
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||||
import cash.z.wallet.sdk.db.CompactBlockDb
|
import cash.z.wallet.sdk.db.CompactBlockDb
|
||||||
import cash.z.wallet.sdk.exception.CompactBlockProcessorException
|
import cash.z.wallet.sdk.exception.CompactBlockProcessorException
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
import cash.z.wallet.sdk.jni.RustBackend
|
||||||
|
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||||
import cash.z.wallet.sdk.rpc.CompactFormats
|
import cash.z.wallet.sdk.rpc.CompactFormats
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
|
@ -21,7 +22,7 @@ import java.io.File
|
||||||
*/
|
*/
|
||||||
class CompactBlockProcessor(
|
class CompactBlockProcessor(
|
||||||
applicationContext: Context,
|
applicationContext: Context,
|
||||||
val converter: JniConverter = JniConverter(),
|
val rustBackend: RustBackendWelding = RustBackend(),
|
||||||
cacheDbName: String = DEFAULT_CACHE_DB_NAME,
|
cacheDbName: String = DEFAULT_CACHE_DB_NAME,
|
||||||
dataDbName: String = DEFAULT_DATA_DB_NAME
|
dataDbName: String = DEFAULT_DATA_DB_NAME
|
||||||
) {
|
) {
|
||||||
|
@ -90,7 +91,7 @@ class CompactBlockProcessor(
|
||||||
twigTask("scanning blocks") {
|
twigTask("scanning blocks") {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
try {
|
try {
|
||||||
converter.scanBlocks(cacheDbPath, dataDbPath)
|
rustBackend.scanBlocks(cacheDbPath, dataDbPath)
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
twig("error while scanning blocks: $t")
|
twig("error while scanning blocks: $t")
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ sealed class SynchronizerException(message: String, cause: Throwable? = null) :
|
||||||
|
|
||||||
sealed class CompactBlockProcessorException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
sealed class CompactBlockProcessorException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
||||||
class DataDbMissing(path: String): CompactBlockProcessorException("No data db file found at path $path. Verify " +
|
class DataDbMissing(path: String): CompactBlockProcessorException("No data db file found at path $path. Verify " +
|
||||||
"that the data DB has been initialized via `converter.initDataDb(path)`")
|
"that the data DB has been initialized via `rustBackend.initDataDb(path)`")
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class CompactBlockStreamException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
sealed class CompactBlockStreamException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
package cash.z.wallet.sdk.jni
|
|
||||||
|
|
||||||
import cash.z.wallet.sdk.annotation.OpenForTesting
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serves as the JNI boundary between the Kotlin and Rust layers. Functions in this class should not be called directly
|
|
||||||
* by code outside of the SDK. Instead, one of the higher-level components should be used such as Wallet.kt or
|
|
||||||
* CompactBlockProcessor.kt.
|
|
||||||
*/
|
|
||||||
@OpenForTesting
|
|
||||||
class JniConverter {
|
|
||||||
|
|
||||||
external fun initDataDb(dbData: String): Boolean
|
|
||||||
|
|
||||||
external fun initAccountsTable(
|
|
||||||
dbData: String,
|
|
||||||
seed: ByteArray,
|
|
||||||
accounts: Int): Array<String>
|
|
||||||
|
|
||||||
external fun initBlocksTable(
|
|
||||||
dbData: String,
|
|
||||||
height: Int,
|
|
||||||
hash: String,
|
|
||||||
time: Long,
|
|
||||||
saplingTree: String): Boolean
|
|
||||||
|
|
||||||
external fun getAddress(dbData: String, account: Int): String
|
|
||||||
|
|
||||||
external fun getBalance(dbData: String, account: Int): Long
|
|
||||||
|
|
||||||
external fun getVerifiedBalance(dbData: String, account: Int): Long
|
|
||||||
|
|
||||||
external fun getReceivedMemoAsUtf8(dbData: String, idNote: Long): String
|
|
||||||
|
|
||||||
external fun getSentMemoAsUtf8(dbData: String, idNote: Long): String
|
|
||||||
|
|
||||||
external fun validateCombinedChain(db_cache: String, db_data: String): Int
|
|
||||||
|
|
||||||
external fun rewindToHeight(db_data: String, height: Int): Boolean
|
|
||||||
|
|
||||||
external fun scanBlocks(db_cache: String, db_data: String): Boolean
|
|
||||||
|
|
||||||
external fun sendToAddress(
|
|
||||||
dbData: String,
|
|
||||||
account: Int,
|
|
||||||
extsk: String,
|
|
||||||
to: String,
|
|
||||||
value: Long,
|
|
||||||
memo: String,
|
|
||||||
spendParams: String,
|
|
||||||
outputParams: String
|
|
||||||
): Long
|
|
||||||
|
|
||||||
external fun initLogs()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
init {
|
|
||||||
System.loadLibrary("zcashwalletsdk")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package cash.z.wallet.sdk.jni
|
||||||
|
|
||||||
|
import cash.z.wallet.sdk.data.twig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serves as the JNI boundary between the Kotlin and Rust layers. Functions in this class should not be called directly
|
||||||
|
* by code outside of the SDK. Instead, one of the higher-level components should be used such as Wallet.kt or
|
||||||
|
* CompactBlockProcessor.kt.
|
||||||
|
*/
|
||||||
|
class RustBackend : RustBackendWelding {
|
||||||
|
|
||||||
|
external override fun initDataDb(dbData: String): Boolean
|
||||||
|
|
||||||
|
external override fun initAccountsTable(
|
||||||
|
dbData: String,
|
||||||
|
seed: ByteArray,
|
||||||
|
accounts: Int): Array<String>
|
||||||
|
|
||||||
|
external override fun initBlocksTable(
|
||||||
|
dbData: String,
|
||||||
|
height: Int,
|
||||||
|
hash: String,
|
||||||
|
time: Long,
|
||||||
|
saplingTree: String): Boolean
|
||||||
|
|
||||||
|
external override fun getAddress(dbData: String, account: Int): String
|
||||||
|
|
||||||
|
external override fun getBalance(dbData: String, account: Int): Long
|
||||||
|
|
||||||
|
external override fun getVerifiedBalance(dbData: String, account: Int): Long
|
||||||
|
|
||||||
|
external override fun getReceivedMemoAsUtf8(dbData: String, idNote: Long): String
|
||||||
|
|
||||||
|
external override fun getSentMemoAsUtf8(dbData: String, idNote: Long): String
|
||||||
|
|
||||||
|
external override fun validateCombinedChain(db_cache: String, db_data: String): Int
|
||||||
|
|
||||||
|
external override fun rewindToHeight(db_data: String, height: Int): Boolean
|
||||||
|
|
||||||
|
external override fun scanBlocks(db_cache: String, db_data: String): Boolean
|
||||||
|
|
||||||
|
external override fun sendToAddress(
|
||||||
|
dbData: String,
|
||||||
|
account: Int,
|
||||||
|
extsk: String,
|
||||||
|
to: String,
|
||||||
|
value: Long,
|
||||||
|
memo: String,
|
||||||
|
spendParams: String,
|
||||||
|
outputParams: String
|
||||||
|
): Long
|
||||||
|
|
||||||
|
external override fun initLogs()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
init {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("zcashwalletsdk")
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
twig("Error while loading native library: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package cash.z.wallet.sdk.jni
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contract defining the exposed capabilitiies of the Rust backend.
|
||||||
|
* This is what welds the SDK to the Rust layer.
|
||||||
|
*/
|
||||||
|
interface RustBackendWelding {
|
||||||
|
|
||||||
|
fun initDataDb(dbData: String): Boolean
|
||||||
|
|
||||||
|
fun initAccountsTable(
|
||||||
|
dbData: String,
|
||||||
|
seed: ByteArray,
|
||||||
|
accounts: Int): Array<String>
|
||||||
|
|
||||||
|
fun initBlocksTable(
|
||||||
|
dbData: String,
|
||||||
|
height: Int,
|
||||||
|
hash: String,
|
||||||
|
time: Long,
|
||||||
|
saplingTree: String): Boolean
|
||||||
|
|
||||||
|
fun getAddress(dbData: String, account: Int): String
|
||||||
|
|
||||||
|
fun getBalance(dbData: String, account: Int): Long
|
||||||
|
|
||||||
|
fun getVerifiedBalance(dbData: String, account: Int): Long
|
||||||
|
|
||||||
|
fun getReceivedMemoAsUtf8(dbData: String, idNote: Long): String
|
||||||
|
|
||||||
|
fun getSentMemoAsUtf8(dbData: String, idNote: Long): String
|
||||||
|
|
||||||
|
fun validateCombinedChain(db_cache: String, db_data: String): Int
|
||||||
|
|
||||||
|
fun rewindToHeight(db_data: String, height: Int): Boolean
|
||||||
|
|
||||||
|
fun scanBlocks(db_cache: String, db_data: String): Boolean
|
||||||
|
|
||||||
|
fun sendToAddress(
|
||||||
|
dbData: String,
|
||||||
|
account: Int,
|
||||||
|
extsk: String,
|
||||||
|
to: String,
|
||||||
|
value: Long,
|
||||||
|
memo: String,
|
||||||
|
spendParams: String,
|
||||||
|
outputParams: String
|
||||||
|
): Long
|
||||||
|
|
||||||
|
fun initLogs()
|
||||||
|
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import cash.z.wallet.sdk.data.twigTask
|
||||||
import cash.z.wallet.sdk.exception.RustLayerException
|
import cash.z.wallet.sdk.exception.RustLayerException
|
||||||
import cash.z.wallet.sdk.exception.WalletException
|
import cash.z.wallet.sdk.exception.WalletException
|
||||||
import cash.z.wallet.sdk.ext.masked
|
import cash.z.wallet.sdk.ext.masked
|
||||||
import cash.z.wallet.sdk.jni.JniConverter
|
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||||
import cash.z.wallet.sdk.secure.Wallet.WalletBirthday
|
import cash.z.wallet.sdk.secure.Wallet.WalletBirthday
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
|
@ -26,14 +26,14 @@ import kotlin.properties.ReadWriteProperty
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for the converter. This class basically represents all the Rust-wallet capabilities and the supporting data
|
* Wrapper for the Rust backend. This class basically represents all the Rust-wallet
|
||||||
* required to exercise those abilities.
|
* capabilities and the supporting data required to exercise those abilities.
|
||||||
*
|
*
|
||||||
* @param birthday the birthday of this wallet. See [WalletBirthday] for more info.
|
* @param birthday the birthday of this wallet. See [WalletBirthday] for more info.
|
||||||
*/
|
*/
|
||||||
class Wallet(
|
class Wallet(
|
||||||
private val birthday: WalletBirthday,
|
private val birthday: WalletBirthday,
|
||||||
private val converter: JniConverter,
|
private val rustBackend: RustBackendWelding,
|
||||||
private val dataDbPath: String,
|
private val dataDbPath: String,
|
||||||
private val paramDestinationDir: String,
|
private val paramDestinationDir: String,
|
||||||
/** indexes of accounts ids. In the reference wallet, we only work with account 0 */
|
/** indexes of accounts ids. In the reference wallet, we only work with account 0 */
|
||||||
|
@ -43,7 +43,7 @@ class Wallet(
|
||||||
) {
|
) {
|
||||||
constructor(
|
constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
converter: JniConverter,
|
rustBackend: RustBackendWelding,
|
||||||
dataDbPath: String,
|
dataDbPath: String,
|
||||||
paramDestinationDir: String,
|
paramDestinationDir: String,
|
||||||
accountIds: Array<Int> = arrayOf(0),
|
accountIds: Array<Int> = arrayOf(0),
|
||||||
|
@ -51,7 +51,7 @@ class Wallet(
|
||||||
spendingKeyProvider: ReadWriteProperty<Any?, String>
|
spendingKeyProvider: ReadWriteProperty<Any?, String>
|
||||||
) : this(
|
) : this(
|
||||||
birthday = loadBirthdayFromAssets(context),
|
birthday = loadBirthdayFromAssets(context),
|
||||||
converter = converter,
|
rustBackend = rustBackend,
|
||||||
dataDbPath = dataDbPath,
|
dataDbPath = dataDbPath,
|
||||||
paramDestinationDir = paramDestinationDir,
|
paramDestinationDir = paramDestinationDir,
|
||||||
accountIds = accountIds,
|
accountIds = accountIds,
|
||||||
|
@ -77,13 +77,13 @@ class Wallet(
|
||||||
firstRunStartHeight: Int = SAPLING_ACTIVATION_HEIGHT
|
firstRunStartHeight: Int = SAPLING_ACTIVATION_HEIGHT
|
||||||
): Int {
|
): Int {
|
||||||
twig("Initializing wallet for first run")
|
twig("Initializing wallet for first run")
|
||||||
converter.initDataDb(dataDbPath)
|
rustBackend.initDataDb(dataDbPath)
|
||||||
twig("seeding the database with sapling tree at height ${birthday.height}")
|
twig("seeding the database with sapling tree at height ${birthday.height}")
|
||||||
converter.initBlocksTable(dataDbPath, birthday.height, birthday.hash, birthday.time, birthday.tree)
|
rustBackend.initBlocksTable(dataDbPath, birthday.height, birthday.hash, birthday.time, birthday.tree)
|
||||||
|
|
||||||
// store the spendingkey by leveraging the utilities provided during construction
|
// store the spendingkey by leveraging the utilities provided during construction
|
||||||
val seed by seedProvider
|
val seed by seedProvider
|
||||||
val accountSpendingKeys = converter.initAccountsTable(dataDbPath, seed, 1)
|
val accountSpendingKeys = rustBackend.initAccountsTable(dataDbPath, seed, 1)
|
||||||
spendingKeyStore = accountSpendingKeys[0]
|
spendingKeyStore = accountSpendingKeys[0]
|
||||||
|
|
||||||
return Math.max(firstRunStartHeight, birthday.height)
|
return Math.max(firstRunStartHeight, birthday.height)
|
||||||
|
@ -93,7 +93,7 @@ class Wallet(
|
||||||
* Gets the address for this wallet, defaulting to the first account.
|
* Gets the address for this wallet, defaulting to the first account.
|
||||||
*/
|
*/
|
||||||
fun getAddress(accountId: Int = accountIds[0]): String {
|
fun getAddress(accountId: Int = accountIds[0]): String {
|
||||||
return converter.getAddress(dataDbPath, accountId)
|
return rustBackend.getAddress(dataDbPath, accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +110,7 @@ class Wallet(
|
||||||
* @param accountId the account to check for balance info. Defaults to zero.
|
* @param accountId the account to check for balance info. Defaults to zero.
|
||||||
*/
|
*/
|
||||||
fun availableBalanceSnapshot(accountId: Int = accountIds[0]): Long {
|
fun availableBalanceSnapshot(accountId: Int = accountIds[0]): Long {
|
||||||
return converter.getVerifiedBalance(dataDbPath, accountId)
|
return rustBackend.getVerifiedBalance(dataDbPath, accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,9 +121,9 @@ class Wallet(
|
||||||
suspend fun sendBalanceInfo(accountId: Int = accountIds[0]) = withContext(IO) {
|
suspend fun sendBalanceInfo(accountId: Int = accountIds[0]) = withContext(IO) {
|
||||||
twigTask("checking balance info") {
|
twigTask("checking balance info") {
|
||||||
try {
|
try {
|
||||||
val balanceTotal = converter.getBalance(dataDbPath, accountId)
|
val balanceTotal = rustBackend.getBalance(dataDbPath, accountId)
|
||||||
twig("found total balance of: $balanceTotal")
|
twig("found total balance of: $balanceTotal")
|
||||||
val balanceAvailable = converter.getVerifiedBalance(dataDbPath, accountId)
|
val balanceAvailable = rustBackend.getVerifiedBalance(dataDbPath, accountId)
|
||||||
twig("found available balance of: $balanceAvailable")
|
twig("found available balance of: $balanceAvailable")
|
||||||
balanceChannel.send(WalletBalance(balanceTotal, balanceAvailable))
|
balanceChannel.send(WalletBalance(balanceTotal, balanceAvailable))
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
|
@ -150,7 +150,7 @@ class Wallet(
|
||||||
result = runCatching {
|
result = runCatching {
|
||||||
ensureParams(paramDestinationDir)
|
ensureParams(paramDestinationDir)
|
||||||
twig("params exist at $paramDestinationDir! attempting to send...")
|
twig("params exist at $paramDestinationDir! attempting to send...")
|
||||||
converter.sendToAddress(
|
rustBackend.sendToAddress(
|
||||||
dataDbPath,
|
dataDbPath,
|
||||||
fromAccountId,
|
fromAccountId,
|
||||||
spendingKeyStore,
|
spendingKeyStore,
|
||||||
|
|
|
@ -46,7 +46,7 @@ use zcash_client_backend::constants::testnet::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initLogs(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_initLogs(
|
||||||
_env: JNIEnv<'_>,
|
_env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
) {
|
) {
|
||||||
|
@ -61,7 +61,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initLogs(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initDataDb(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_initDataDb(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -77,7 +77,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initDataDb(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initAccountsTable(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_initAccountsTable(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -121,7 +121,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initAccountsTab
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initBlocksTable(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_initBlocksTable(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -154,7 +154,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initBlocksTable
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getAddress(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_getAddress(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -180,7 +180,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getAddress(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getBalance(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_getBalance(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -203,7 +203,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getBalance(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getVerifiedBalance(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_getVerifiedBalance(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -226,7 +226,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getVerifiedBala
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getReceivedMemoAsUtf8(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_getReceivedMemoAsUtf8(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -247,7 +247,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getReceivedMemo
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getSentMemoAsUtf8(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_getSentMemoAsUtf8(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -268,7 +268,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getSentMemoAsUt
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_validateCombinedChain(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_validateCombinedChain(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_cache: JString<'_>,
|
db_cache: JString<'_>,
|
||||||
|
@ -292,7 +292,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_validateCombine
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_rewindToHeight(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_rewindToHeight(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
@ -314,7 +314,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_rewindToHeight(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_scanBlocks(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_scanBlocks(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_cache: JString<'_>,
|
db_cache: JString<'_>,
|
||||||
|
@ -333,7 +333,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_scanBlocks(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_sendToAddress(
|
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_sendToAddress(
|
||||||
env: JNIEnv<'_>,
|
env: JNIEnv<'_>,
|
||||||
_: JClass<'_>,
|
_: JClass<'_>,
|
||||||
db_data: JString<'_>,
|
db_data: JString<'_>,
|
||||||
|
|
Loading…
Reference in New Issue