Add ability to erase by alias.

This commit is contained in:
Kevin Gorham 2020-10-30 09:20:32 -04:00
parent 9779a1aa8f
commit 4e2065e0df
4 changed files with 101 additions and 44 deletions

View File

@ -3,22 +3,37 @@ package cash.z.ecc.android.sdk
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import org.junit.Assert.assertEquals
import org.junit.Assert.*
import org.junit.Test
class InitializerTest {
@Test
fun testInit() {
val height = 1_419_900
val height = 980000
val initializer = Initializer(context) { config ->
config.importedWalletBirthday(height)
config.setViewingKeys("zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
"zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7")
config.alias = "VkInitTest2"
config.alias = "VkInitTest1"
}
assertEquals(height, initializer.birthday.height)
initializer.erase()
}
@Test
fun testErase() {
val alias = "VkInitTest2"
Initializer(context) { config ->
config.importedWalletBirthday(1_419_900)
config.setViewingKeys("zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
"zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7")
config.alias = alias
}
assertFalse("Expected false when erasing nothing.", Initializer.erase(context))
assertTrue("Failed to erase initializer", Initializer.erase(context, alias))
}
companion object {

View File

@ -45,6 +45,7 @@ class Initializer constructor(appContext: Context, builder: Builder): SdkSynchr
constructor(appContext: Context, block: (Builder) -> Unit) : this(appContext, Builder(block))
fun erase() = erase(context, alias)
private fun initRustBackend(birthday: WalletBirthdayTool.WalletBirthday): RustBackend {
return RustBackend.init(
@ -104,45 +105,6 @@ class Initializer constructor(appContext: Context, builder: Builder): SdkSynchr
}
}
/**
* Delete all local data related to this wallet, as though the wallet was never created on this
* device. Simply put, this call deletes the "cache db" and "data db."
*/
override fun clear() {
rustBackend.clear()
}
//
// Path Helpers
//
/**
* Returns the path to the cache database that would correspond to the given alias.
*
* @param appContext the application context
* @param alias the alias to convert into a database path
*/
fun cacheDbPath(appContext: Context, alias: String): String =
aliasToPath(appContext, alias, ZcashSdk.DB_CACHE_NAME)
/**
* Returns the path to the data database that would correspond to the given alias.
* @param appContext the application context
* @param alias the alias to convert into a database path
*/
fun dataDbPath(appContext: Context, alias: String): String =
aliasToPath(appContext, alias, ZcashSdk.DB_DATA_NAME)
private fun aliasToPath(appContext: Context, alias: String, dbFileName: String): String {
val parentDir: String =
appContext.getDatabasePath("unused.db").parentFile?.absolutePath
?: throw InitializerException.DatabasePathException
val prefix = if (alias.endsWith('_')) alias else "${alias}_"
return File(parentDir, "$prefix$dbFileName").absolutePath
}
/**
* Validate that the alias doesn't contain malicious characters by enforcing simple rules which
* permit the alias to be used as part of a file name for the preferences and databases. This
@ -351,6 +313,74 @@ class Initializer constructor(appContext: Context, builder: Builder): SdkSynchr
}
}
}
companion object : SdkSynchronizer.Erasable {
/**
* Delete the databases associated with this wallet. This removes all compact blocks and
* data derived from those blocks. For most wallets, this should not result in a loss of
* funds because the seed and spending keys are stored separately. This call just removes
* the associated data but not the seed or spending key, themselves, because those are
* managed separately by the wallet.
*
* @param appContext the application context.
* @param alias the alias used to create the local data.
*
* @return true when associated files were found. False most likely indicates that the wrong
* alias was provided.
*/
override fun erase(appContext: Context, alias: String) =
delete(cacheDbPath(appContext, alias)) || delete(dataDbPath(appContext, alias))
//
// Path Helpers
//
/**
* Returns the path to the cache database that would correspond to the given alias.
*
* @param appContext the application context
* @param alias the alias to convert into a database path
*/
internal fun cacheDbPath(appContext: Context, alias: String): String =
aliasToPath(appContext, alias, ZcashSdk.DB_CACHE_NAME)
/**
* Returns the path to the data database that would correspond to the given alias.
* @param appContext the application context
* @param alias the alias to convert into a database path
*/
internal fun dataDbPath(appContext: Context, alias: String): String =
aliasToPath(appContext, alias, ZcashSdk.DB_DATA_NAME)
private fun aliasToPath(appContext: Context, alias: String, dbFileName: String): String {
val parentDir: String =
appContext.getDatabasePath("unused.db").parentFile?.absolutePath
?: throw InitializerException.DatabasePathException
val prefix = if (alias.endsWith('_')) alias else "${alias}_"
return File(parentDir, "$prefix$dbFileName").absolutePath
}
/**
* Delete the file at the given path.
*
* @param filePath the path of the file to erase.
* @return true when a file exists at the given path and was deleted.
*/
private fun delete(filePath: String) : Boolean {
return File(filePath).let {
if (it.exists()) {
twig("Deleting ${it.name}!")
it.delete()
true
} else {
false
}
}
}
}
}
/**

View File

@ -523,7 +523,19 @@ class SdkSynchronizer internal constructor(
val host: String
val port: Int
val alias: String
fun clear()
}
interface Erasable {
/**
* Erase content related to this SDK.
*
* @param appContext the application context.
* @param alias identifier for SDK content. It is possible for multiple synchronizers to
* exist with different aliases.
*
* @return true when content was found for the given alias. False otherwise.
*/
fun erase(appContext: Context, alias: String = ZcashSdk.DEFAULT_ALIAS): Boolean
}
}

View File

@ -65,7 +65,7 @@ class CompactBlockProcessor(
var onProcessorErrorListener: ((Throwable) -> Boolean)? = null
/**
* Callbaqck for reorgs. This callback is invoked when validation fails with the height at which
* Callback for reorgs. This callback is invoked when validation fails with the height at which
* an error was found and the lower bound to which the data will rewind, at most.
*/
var onChainErrorListener: ((errorHeight: Int, rewindHeight: Int) -> Any)? = null