Fixed tests.
This commit is contained in:
parent
ac7f3475e9
commit
a572b55db0
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
// }
|
||||
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue