Fixed tests.

This commit is contained in:
Kevin Gorham 2020-02-21 18:15:13 -05:00
parent ac7f3475e9
commit a572b55db0
No known key found for this signature in database
GPG Key ID: CCA55602DF49FC38
5 changed files with 266 additions and 39 deletions

View File

@ -1,51 +1,46 @@
package cash.z.wallet.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.wallet.sdk.ext.TroubleshootingTwig
import cash.z.wallet.sdk.ext.Twig
import cash.z.wallet.sdk.ext.SampleSeedProvider
import cash.z.wallet.sdk.jni.RustBackend
import cash.z.wallet.sdk.secure.Wallet
import cash.z.wallet.sdk.Initializer
import cash.z.wallet.sdk.Initializer.WalletBirthday
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
import okio.Okio
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Assert.assertTrue
import org.junit.Test
import java.io.IOException
import kotlin.properties.Delegates
import kotlin.properties.ReadWriteProperty
@ExperimentalCoroutinesApi
class AddressGeneratorUtil {
private val dataDbName = "AddressUtilData.db"
private val context = InstrumentationRegistry.getInstrumentation().context
private val rustBackend = RustBackend.init(context)
private val initializer = Initializer(context).open(WalletBirthday())
private val mnemonics = SimpleMnemonics()
private lateinit var wallet: Wallet
@Before
fun setup() {
Twig.plant(TroubleshootingTwig())
}
private fun deleteDb() {
context.getDatabasePath(dataDbName).absoluteFile.delete()
@Test
fun printMnemonic() {
mnemonics.apply {
val mnemonicPhrase = String(nextMnemonic())
println("example mnemonic: $mnemonicPhrase")
assertEquals(24, mnemonicPhrase.split(" ").size)
}
}
@Test
fun generateAddresses() = runBlocking {
readLines().collect { seed ->
val keyStore = initWallet(seed)
val address = wallet.getAddress()
val pk by keyStore
println("xrxrx2\t$seed\t$address\t$pk")
}
Thread.sleep(5000)
assertEquals("foo", "bar")
readLines()
.map { seedPhrase ->
mnemonics.toSeed(seedPhrase.toCharArray())
}.map { seed ->
initializer.rustBackend.deriveAddress(seed)
}.collect { address ->
println("xrxrx2\t$address")
assertTrue(address.startsWith("zs1"))
}
}
@Throws(IOException::class)
@ -60,11 +55,4 @@ class AddressGeneratorUtil {
}
}
private fun initWallet(seed: String): ReadWriteProperty<Any?, String> {
deleteDb()
val spendingKeyProvider = Delegates.notNull<String>()
wallet = Wallet(context, rustBackend, SampleSeedProvider(seed), spendingKeyProvider)
wallet.initialize()
return spendingKeyProvider
}
}

View File

@ -0,0 +1,143 @@
package cash.z.wallet.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.wallet.sdk.Initializer
import cash.z.wallet.sdk.SdkSynchronizer
import cash.z.wallet.sdk.Synchronizer
import cash.z.wallet.sdk.block.CompactBlockDbStore
import cash.z.wallet.sdk.block.CompactBlockDownloader
import cash.z.wallet.sdk.block.CompactBlockProcessor
import cash.z.wallet.sdk.ext.TroubleshootingTwig
import cash.z.wallet.sdk.ext.Twig
import cash.z.wallet.sdk.ext.twig
import cash.z.wallet.sdk.service.LightWalletGrpcService
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okio.Okio
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import java.io.IOException
/**
* A tool for validating an existing database and testing reorgs.
*/
@ExperimentalCoroutinesApi
class DataDbScannerUtil {
private val context = InstrumentationRegistry.getInstrumentation().context
private val host = "lightd-main.zecwallet.co"
private val port = 443
private val alias = "ScannerUtil"
// private val mnemonics = SimpleMnemonics()
// private val caceDbPath = Initializer.cacheDbPath(context, alias)
// private val downloader = CompactBlockDownloader(
// LightWalletGrpcService(context, host, port),
// CompactBlockDbStore(context, caceDbPath)
// )
// private val processor = CompactBlockProcessor(downloader)
// private val rustBackend = RustBackend.init(context, cacheDbName, dataDbName)
private val initializer = Initializer(context, host, port, alias)
private lateinit var birthday: Initializer.WalletBirthday
private val birthdayHeight = 600_000
private lateinit var synchronizer: Synchronizer
@Before
fun setup() {
Twig.plant(TroubleshootingTwig())
// cacheBlocks()
birthday = Initializer.DefaultBirthdayStore(context, birthdayHeight, alias).getBirthday()
}
private fun cacheBlocks() = runBlocking {
// twig("downloading compact blocks...")
// val latestBlockHeight = downloader.getLatestBlockHeight()
// val lastDownloaded = downloader.getLastDownloadedHeight()
// val blockRange = (Math.max(birthday, lastDownloaded))..latestBlockHeight
// downloadNewBlocks(blockRange)
// val error = validateNewBlocks(blockRange)
// twig("validation completed with result $error")
// assertEquals(-1, error)
}
private fun deleteDb(dbName: String) {
context.getDatabasePath(dbName).absoluteFile.delete()
}
@Test
fun scanExistingDb() {
initializer.open(birthday)
synchronizer = Synchronizer(context, initializer)
println("sync!")
synchronizer.start()
val scope = (synchronizer as SdkSynchronizer).coroutineScope
scope.launch {
synchronizer.status.collect { status ->
// when (status) {
println("received status of $status")
// }
}
}
println("going to sleep!")
Thread.sleep(125000)
println("I'm back and I'm out!")
synchronizer.stop()
}
//
// @Test
// fun printBalances() = runBlocking {
// readLines()
// .map { seedPhrase ->
// twig("checking balance for: $seedPhrase")
// mnemonics.toSeed(seedPhrase.toCharArray())
// }.collect { seed ->
// initializer.import(seed, birthday, clearDataDb = true, clearCacheDb = false)
// /*
// what I need to do right now
// - for each seed
// - I can reuse the cache of blocks... so just like get the cache once
// - I need to scan into a new database
// - I don't really need a new rustbackend
// - I definitely don't need a new grpc connection
// - can I just use a processor and point it to a different DB?
// + so yeah, I think I need to use the processor directly right here and just swap out its pieces
// - perhaps create a new initializer and use that to configure the processor?
// - or maybe just set the data destination for the processor
// - I might need to consider how state is impacting this design
// - can we be more stateless and thereby improve the flexibility of this code?!!!
// */
// synchronizer?.stop()
// synchronizer = Synchronizer(context, initializer)
//
//// deleteDb(dataDbPath)
//// initWallet(seed)
//// twig("scanning blocks for seed <$seed>")
////// rustBackend.scanBlocks()
//// twig("done scanning blocks for seed $seed")
////// val total = rustBackend.getBalance(0)
//// twig("found total: $total")
////// val available = rustBackend.getVerifiedBalance(0)
//// twig("found available: $available")
//// twig("xrxrx2\t$seed\t$total\t$available")
//// println("xrxrx2\t$seed\t$total\t$available")
// }
//
// Thread.sleep(5000)
// assertEquals("foo", "bar")
// }
}

View File

@ -0,0 +1,82 @@
package cash.z.wallet.sdk.util
import cash.z.android.plugin.MnemonicPlugin
import io.github.novacrypto.bip39.MnemonicGenerator
import io.github.novacrypto.bip39.SeedCalculator
import io.github.novacrypto.bip39.Words
import io.github.novacrypto.bip39.wordlists.English
import java.security.SecureRandom
class SimpleMnemonics : MnemonicPlugin {
override fun nextEntropy(): ByteArray {
return ByteArray(Words.TWENTY_FOUR.byteLength()).apply {
SecureRandom().nextBytes(this)
}
}
override fun nextMnemonic(): CharArray {
return nextMnemonic(nextEntropy())
}
override fun nextMnemonic(entropy: ByteArray): CharArray {
return StringBuilder().let { builder ->
MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c ->
builder.append(c)
}
builder.toString().toCharArray()
}
}
override fun nextMnemonicList(): List<CharArray> {
return nextMnemonicList(nextEntropy())
}
override fun nextMnemonicList(entropy: ByteArray): List<CharArray> {
return WordListBuilder().let { builder ->
MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c ->
builder.append(c)
}
builder.wordList
}
}
override fun toSeed(mnemonic: CharArray): ByteArray {
return SeedCalculator().calculateSeed(String(mnemonic), "")
}
override fun toWordList(mnemonic: CharArray): List<CharArray> {
val wordList = mutableListOf<CharArray>()
var cursor = 0
repeat(mnemonic.size) { i ->
val isSpace = mnemonic[i] == ' '
if (isSpace || i == (mnemonic.size - 1)) {
val wordSize = i - cursor + if (isSpace) 0 else 1
wordList.add(CharArray(wordSize).apply {
repeat(wordSize) {
this[it] = mnemonic[cursor + it]
}
})
cursor = i + 1
}
}
return wordList
}
class WordListBuilder {
val wordList = mutableListOf<CharArray>()
fun append(c: CharSequence) {
if (c[0] != English.INSTANCE.space) addWord(c)
}
private fun addWord(c: CharSequence) {
c.length.let { size ->
val word = CharArray(size)
repeat(size) {
word[it] = c[it]
}
wordList.add(word)
}
}
}
}

View File

@ -1,3 +1,17 @@
seed-1
seed-2
seed-3
urban kind wise collect social marble riot primary craft lucky head cause syrup odor artist decorate rhythm phone style benefit portion bus truck top
wish puppy smile loan doll curve hole maze file ginger hair nose key relax knife witness cannon grab despair throw review deal slush frame
labor elite banana cement royal tiger smile robust talk street bread bitter admit spy leg alcohol opinion mimic crane bid damp trigger wagon share
icon future member loan initial music bless cigar artist cross scorpion disease click else palm recall obscure horse wire energy frost route stone raven
way fruit group range army seven stem ridge panel duty deal like mango engage adult market drama large year love clay desert culture evoke
stairs bridge romance offer bronze organ soldier point unveil soup figure economy purity rapid eight error make goat poet when letter gold coil gate
execute thing home flat rare pitch plug poverty never design cute essay mosquito unhappy pen phone aerobic basket empower system extend concert leopard leopard
thought balcony raw renew sister define isolate bridge rigid critic extra enhance accuse skin either lock owner boat grid legal coral judge oyster olympic
pull curious short apology slot giraffe island caution cricket attract episode acoustic age fly crucial earth broccoli eternal eyebrow marriage lazy thank actor police
army boat guess direct network version mean rice brown sauce bronze health stable way proud gift primary reason company raw sorry virtual other ahead
humble educate desert govern quality cup illness spatial whale zoo novel hollow velvet erosion gadget glove great occur milk staff gravity word skate soul
horror scene device ahead before blossom surface staff shrug horse wood drill style garage north account twice easily slam require nose sentence catalog mango
bronze this era window wonder strike label grid keep paddle kiwi age input flock just eagle coil like toward burst mobile obtain giant idle
aisle dwarf bulb catch anxiety follow attack that habit exclude laptop spoon enough walnut picture reward pact license behind question save cover exotic drip
two length electric immune antique rotate junior spoon torch liberty eyebrow shoe army away horn anger oak chase grow ride enrich soft push orient
bike crunch vintage smoke okay screen side pattern thrive top timber payment flight garment lift heavy enable sting humble obscure reveal art kangaroo owner
treat stumble only reward else turtle across shop vocal dynamic goddess toss review polar enable plate process cabin injury rifle sword group agree slush

View File

@ -50,7 +50,7 @@ class IntegrationTest {
fun testBalance() = runBlocking {
var availableBalance: Long = 0L
synchronizer.balances.onFirst {
availableBalance = it.available
availableBalance = it.availableZatoshi
}
synchronizer.status.filter { it == SYNCED }.onFirst {
@ -65,7 +65,7 @@ class IntegrationTest {
@Ignore
fun testSpend() = runBlocking {
var success = false
synchronizer.balances.filter { it.available > 0 }.onEach {
synchronizer.balances.filter { it.availableZatoshi > 0 }.onEach {
success = sendFunds()
}.first()
log("asserting $success")