Add data access layer for dataDb
Update the scanBlocks request and integrate with the data that it generates inside dataDb
This commit is contained in:
parent
a1f4491fba
commit
1501f1a7d2
|
@ -0,0 +1,39 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS blocks (
|
||||||
|
height INTEGER PRIMARY KEY,
|
||||||
|
time INTEGER,
|
||||||
|
sapling_tree BLOB
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS transactions (
|
||||||
|
id_tx INTEGER PRIMARY KEY,
|
||||||
|
txid BLOB NOT NULL UNIQUE,
|
||||||
|
block INTEGER,
|
||||||
|
raw BLOB,
|
||||||
|
FOREIGN KEY (block) REFERENCES blocks(height)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS received_notes (
|
||||||
|
id_note INTEGER PRIMARY KEY,
|
||||||
|
tx INTEGER NOT NULL,
|
||||||
|
output_index INTEGER NOT NULL,
|
||||||
|
account INTEGER NOT NULL,
|
||||||
|
diversifier BLOB NOT NULL,
|
||||||
|
value INTEGER NOT NULL,
|
||||||
|
rcm BLOB NOT NULL,
|
||||||
|
nf BLOB NOT NULL UNIQUE,
|
||||||
|
memo BLOB,
|
||||||
|
spent INTEGER,
|
||||||
|
FOREIGN KEY (tx) REFERENCES transactions(id_tx),
|
||||||
|
FOREIGN KEY (spent) REFERENCES transactions(id_tx),
|
||||||
|
CONSTRAINT tx_output UNIQUE (tx, output_index)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS sapling_witnesses (
|
||||||
|
id_witness INTEGER PRIMARY KEY,
|
||||||
|
note INTEGER NOT NULL,
|
||||||
|
block INTEGER NOT NULL,
|
||||||
|
witness BLOB NOT NULL,
|
||||||
|
FOREIGN KEY (note) REFERENCES received_notes(id_note),
|
||||||
|
FOREIGN KEY (block) REFERENCES blocks(height),
|
||||||
|
CONSTRAINT witness_height UNIQUE (note, block)
|
||||||
|
);
|
10
build.gradle
10
build.gradle
|
@ -29,7 +29,7 @@ apply plugin: 'com.github.ben-manes.versions'
|
||||||
apply plugin: 'com.github.dcendents.android-maven'
|
apply plugin: 'com.github.dcendents.android-maven'
|
||||||
|
|
||||||
group = 'cash.z.android.wallet'
|
group = 'cash.z.android.wallet'
|
||||||
version = '1.2.0'
|
version = '1.2.4'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
@ -42,8 +42,8 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode = 1_02_00
|
versionCode = 1_02_03
|
||||||
versionName = "1.2.0"
|
versionName = "1.2.3"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package cash.z.wallet.sdk.dao
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import cash.z.wallet.sdk.db.CompactBlockDb
|
||||||
|
import cash.z.wallet.sdk.db.DerivedDataDb
|
||||||
|
import cash.z.wallet.sdk.vo.CompactBlock
|
||||||
|
import cash.z.wallet.sdk.vo.Transaction
|
||||||
|
import org.junit.*
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
class TransactionDaoTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
|
private lateinit var dao: TransactionDao
|
||||||
|
private lateinit var db: DerivedDataDb
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun initDb() {
|
||||||
|
db = Room.inMemoryDatabaseBuilder(
|
||||||
|
InstrumentationRegistry.getInstrumentation().context,
|
||||||
|
DerivedDataDb::class.java
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
.apply { dao = transactionDao() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun close() {
|
||||||
|
db.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDbExists() {
|
||||||
|
assertNotNull(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDaoExists() {
|
||||||
|
assertNotNull(dao)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDaoInsert() {
|
||||||
|
Transaction(4, "sample".toByteArray(), 356418, null).let { transaction ->
|
||||||
|
dao.insert(transaction)
|
||||||
|
val result = dao.findById(transaction.id)
|
||||||
|
assertEquals(transaction.id, result?.id)
|
||||||
|
assertTrue(transaction.transactionId.contentEquals(result!!.transactionId))
|
||||||
|
dao.delete(transaction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import cash.z.wallet.sdk.vo.CompactBlock
|
||||||
import org.junit.*
|
import org.junit.*
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.*
|
||||||
|
|
||||||
class DbIntegrationTest {
|
class CacheDbIntegrationTest {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ class DbIntegrationTest {
|
||||||
fun setup() {
|
fun setup() {
|
||||||
// TODO: put this database in the assets directory and open it from there via .openHelperFactory(new AssetSQLiteOpenHelperFactory()) seen here https://github.com/albertogiunta/sqliteAsset
|
// TODO: put this database in the assets directory and open it from there via .openHelperFactory(new AssetSQLiteOpenHelperFactory()) seen here https://github.com/albertogiunta/sqliteAsset
|
||||||
db = Room
|
db = Room
|
||||||
.databaseBuilder(ApplicationProvider.getApplicationContext(), CompactBlockDb::class.java, "compact-blocks.db")
|
.databaseBuilder(ApplicationProvider.getApplicationContext(), CompactBlockDb::class.java, "dummy-cache.db")
|
||||||
|
// .databaseBuilder(ApplicationProvider.getApplicationContext(), CompactBlockDb::class.java, "compact-blocks.db")
|
||||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
.build()
|
.build()
|
|
@ -0,0 +1,95 @@
|
||||||
|
package cash.z.wallet.sdk.db
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import cash.z.wallet.sdk.dao.BlockDao
|
||||||
|
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||||
|
import cash.z.wallet.sdk.dao.NoteDao
|
||||||
|
import cash.z.wallet.sdk.dao.TransactionDao
|
||||||
|
import cash.z.wallet.sdk.vo.CompactBlock
|
||||||
|
import org.junit.*
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
class DerivedDbIntegrationTest {
|
||||||
|
@get:Rule
|
||||||
|
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDbExists() {
|
||||||
|
assertNotNull(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDaoExists_Transaction() {
|
||||||
|
assertNotNull(transactions)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDaoExists_Block() {
|
||||||
|
assertNotNull(blocks)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDaoExists_Note() {
|
||||||
|
assertNotNull(notes)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCount_Transaction() {
|
||||||
|
assertEquals(5, transactions.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCount_Block() {
|
||||||
|
assertEquals(80101, blocks.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCount_Note() {
|
||||||
|
assertEquals(5, notes.count())
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun testTransactionDaoPrepopulated() {
|
||||||
|
val tran = transactions.findById(1)
|
||||||
|
|
||||||
|
assertEquals(343987, tran?.block)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBlockDaoPrepopulated() {
|
||||||
|
val tran = blocks.findById(1)?.apply {
|
||||||
|
assertEquals(343987, this.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private lateinit var transactions: TransactionDao
|
||||||
|
private lateinit var blocks: BlockDao
|
||||||
|
private lateinit var notes: NoteDao
|
||||||
|
private lateinit var db: DerivedDataDb
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
@JvmStatic
|
||||||
|
fun setup() {
|
||||||
|
// TODO: put this database in the assets directory and open it from there via .openHelperFactory(new AssetSQLiteOpenHelperFactory()) seen here https://github.com/albertogiunta/sqliteAsset
|
||||||
|
db = Room
|
||||||
|
.databaseBuilder(ApplicationProvider.getApplicationContext(), DerivedDataDb::class.java, "dummy-data2.db")
|
||||||
|
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build()
|
||||||
|
.apply {
|
||||||
|
transactions = transactionDao()
|
||||||
|
blocks = blockDao()
|
||||||
|
notes = noteDao()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
@JvmStatic
|
||||||
|
fun close() {
|
||||||
|
db.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package cash.z.wallet.sdk.jni
|
package cash.z.wallet.sdk.jni
|
||||||
|
|
||||||
|
import android.text.format.DateUtils
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
|
@ -23,12 +24,13 @@ class JniConverterTest {
|
||||||
fun testScanBlocks() {
|
fun testScanBlocks() {
|
||||||
// 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 = converter.scanBlocks(
|
||||||
"/data/user/0/cash.z.wallet.sdk.test/databases/compact-block.db",
|
"/data/user/0/cash.z.wallet.sdk.test/databases/dummy-cache.db",
|
||||||
343900,
|
"/data/user/0/cash.z.wallet.sdk.test/databases/data.db",
|
||||||
344855,
|
"dummyseed".toByteArray(),
|
||||||
"dummyseed".toByteArray()
|
343900
|
||||||
)
|
)
|
||||||
assertEquals("Invalid number of results", 2, result.size)
|
// Thread.sleep(15 * DateUtils.MINUTE_IN_MILLIS)
|
||||||
|
assertEquals("Invalid number of results", 2, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package cash.z.wallet.sdk.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import cash.z.wallet.sdk.vo.Block
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface BlockDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insert(block: Block)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM blocks WHERE height = :height")
|
||||||
|
fun findById(height: Int): Block?
|
||||||
|
|
||||||
|
@Query("DELETE FROM blocks WHERE height = :height")
|
||||||
|
fun deleteById(height: Int)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(block: Block)
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(height) FROM blocks")
|
||||||
|
fun count(): Int
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cash.z.wallet.sdk.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import cash.z.wallet.sdk.vo.Note
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface NoteDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insert(block: Note)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM received_notes WHERE id_note = :id")
|
||||||
|
fun findById(id: Int): Note?
|
||||||
|
|
||||||
|
@Query("DELETE FROM received_notes WHERE id_note = :id")
|
||||||
|
fun deleteById(id: Int)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM received_notes WHERE 1")
|
||||||
|
fun getAll(): List<Note>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(block: Note)
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(id_note) FROM received_notes")
|
||||||
|
fun count(): Int
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package cash.z.wallet.sdk.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import cash.z.wallet.sdk.vo.Transaction
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface TransactionDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insert(block: Transaction)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM transactions WHERE id_tx = :id")
|
||||||
|
fun findById(id: Int): Transaction?
|
||||||
|
|
||||||
|
@Query("DELETE FROM transactions WHERE id_tx = :id")
|
||||||
|
fun deleteById(id: Int)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM transactions WHERE 1")
|
||||||
|
fun getAll(): List<Transaction>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(block: Transaction)
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(id_tx) FROM transactions")
|
||||||
|
fun count(): Int
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cash.z.wallet.sdk.db
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import cash.z.wallet.sdk.dao.BlockDao
|
||||||
|
import cash.z.wallet.sdk.dao.NoteDao
|
||||||
|
import cash.z.wallet.sdk.dao.TransactionDao
|
||||||
|
import cash.z.wallet.sdk.vo.Block
|
||||||
|
import cash.z.wallet.sdk.vo.Note
|
||||||
|
import cash.z.wallet.sdk.vo.Transaction
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [
|
||||||
|
Transaction::class,
|
||||||
|
Block::class,
|
||||||
|
Note::class
|
||||||
|
],
|
||||||
|
version = 1,
|
||||||
|
exportSchema = false
|
||||||
|
)
|
||||||
|
abstract class DerivedDataDb : RoomDatabase() {
|
||||||
|
abstract fun transactionDao(): TransactionDao
|
||||||
|
abstract fun noteDao(): NoteDao
|
||||||
|
abstract fun blockDao(): BlockDao
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cash.z.wallet.sdk.vo
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
|
||||||
|
@Entity(primaryKeys = ["height"], tableName = "blocks")
|
||||||
|
data class Block(
|
||||||
|
val height: Int,
|
||||||
|
val time: Int,
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB, name = "sapling_tree")
|
||||||
|
val saplingTree: ByteArray
|
||||||
|
) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
return (other is Block)
|
||||||
|
&& height == other.height
|
||||||
|
&& time == other.time
|
||||||
|
&& saplingTree.contentEquals(other.saplingTree)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = height
|
||||||
|
result = 31 * result + time
|
||||||
|
result = 31 * result + saplingTree.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package cash.z.wallet.sdk.vo
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
tableName = "received_notes",
|
||||||
|
primaryKeys = ["id_note"],
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Transaction::class,
|
||||||
|
parentColumns = ["id_tx"],
|
||||||
|
childColumns = ["tx"],
|
||||||
|
onUpdate = ForeignKey.CASCADE,
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
), ForeignKey(
|
||||||
|
entity = Transaction::class,
|
||||||
|
parentColumns = ["id_tx"],
|
||||||
|
childColumns = ["spent"],
|
||||||
|
onUpdate = ForeignKey.CASCADE,
|
||||||
|
onDelete = ForeignKey.SET_NULL
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
data class Note(
|
||||||
|
@ColumnInfo(name = "id_note")
|
||||||
|
val id: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "tx")
|
||||||
|
val transaction: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "output_index")
|
||||||
|
val outputIndex: Int,
|
||||||
|
|
||||||
|
val account: Int,
|
||||||
|
val value: Int,
|
||||||
|
val spent: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||||
|
val diversifier: ByteArray,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||||
|
val rcm: ByteArray,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||||
|
val nf: ByteArray,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||||
|
val memo: ByteArray?
|
||||||
|
) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
|
||||||
|
return (other is Note)
|
||||||
|
&& id == other.id
|
||||||
|
&& transaction == other.transaction
|
||||||
|
&& outputIndex == other.outputIndex
|
||||||
|
&& account == other.account
|
||||||
|
&& value == other.value
|
||||||
|
&& spent == other.spent
|
||||||
|
&& diversifier.contentEquals(other.diversifier)
|
||||||
|
&& rcm.contentEquals(other.rcm)
|
||||||
|
&& nf.contentEquals(other.nf)
|
||||||
|
&& ((memo == null && other.memo == null) || (memo != null && other.memo != null && memo.contentEquals(other.memo)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + transaction
|
||||||
|
result = 31 * result + outputIndex
|
||||||
|
result = 31 * result + account
|
||||||
|
result = 31 * result + value
|
||||||
|
result = 31 * result + spent
|
||||||
|
result = 31 * result + diversifier.contentHashCode()
|
||||||
|
result = 31 * result + rcm.contentHashCode()
|
||||||
|
result = 31 * result + nf.contentHashCode()
|
||||||
|
result = 31 * result + (memo?.contentHashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cash.z.wallet.sdk.vo
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
primaryKeys = ["id_tx"], tableName = "transactions",
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Block::class,
|
||||||
|
parentColumns = ["height"],
|
||||||
|
childColumns = ["block"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
data class Transaction(
|
||||||
|
@ColumnInfo(name = "id_tx")
|
||||||
|
val id: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB, name = "txid")
|
||||||
|
@NotNull
|
||||||
|
val transactionId: ByteArray,
|
||||||
|
|
||||||
|
val block: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||||
|
val raw: ByteArray?
|
||||||
|
) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
|
||||||
|
return (other is Transaction)
|
||||||
|
&& id == other.id
|
||||||
|
&& transactionId.contentEquals(other.transactionId)
|
||||||
|
&& block == other.block
|
||||||
|
&& ((raw == null && other.raw == null) || (raw != null && other.raw != null && raw.contentEquals(other.raw)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id
|
||||||
|
result = 31 * result + transactionId.contentHashCode()
|
||||||
|
result = 31 * result + block
|
||||||
|
result = 31 * result + (raw?.contentHashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
// This file is generated by rust-protobuf 2.2.0. Do not edit
|
||||||
|
// @generated
|
||||||
|
|
||||||
|
// https://github.com/Manishearth/rust-clippy/issues/702
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy)]
|
||||||
|
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
#![allow(box_pointers)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(trivial_casts)]
|
||||||
|
#![allow(unsafe_code)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unused_results)]
|
||||||
|
|
||||||
|
use protobuf::Message as Message_imported_for_functions;
|
||||||
|
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
|
||||||
|
|
||||||
|
#[derive(PartialEq,Clone,Default)]
|
||||||
|
pub struct ValueReceived {
|
||||||
|
// message fields
|
||||||
|
pub blockHeight: u64,
|
||||||
|
pub txHash: ::std::vec::Vec<u8>,
|
||||||
|
pub value: u64,
|
||||||
|
// special fields
|
||||||
|
pub unknown_fields: ::protobuf::UnknownFields,
|
||||||
|
pub cached_size: ::protobuf::CachedSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueReceived {
|
||||||
|
pub fn new() -> ValueReceived {
|
||||||
|
::std::default::Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint64 blockHeight = 1;
|
||||||
|
|
||||||
|
pub fn clear_blockHeight(&mut self) {
|
||||||
|
self.blockHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_blockHeight(&mut self, v: u64) {
|
||||||
|
self.blockHeight = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_blockHeight(&self) -> u64 {
|
||||||
|
self.blockHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// bytes txHash = 2;
|
||||||
|
|
||||||
|
pub fn clear_txHash(&mut self) {
|
||||||
|
self.txHash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_txHash(&mut self, v: ::std::vec::Vec<u8>) {
|
||||||
|
self.txHash = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable pointer to the field.
|
||||||
|
// If field is not initialized, it is initialized with default value first.
|
||||||
|
pub fn mut_txHash(&mut self) -> &mut ::std::vec::Vec<u8> {
|
||||||
|
&mut self.txHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take field
|
||||||
|
pub fn take_txHash(&mut self) -> ::std::vec::Vec<u8> {
|
||||||
|
::std::mem::replace(&mut self.txHash, ::std::vec::Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_txHash(&self) -> &[u8] {
|
||||||
|
&self.txHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint64 value = 3;
|
||||||
|
|
||||||
|
pub fn clear_value(&mut self) {
|
||||||
|
self.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_value(&mut self, v: u64) {
|
||||||
|
self.value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u64 {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Message for ValueReceived {
|
||||||
|
fn is_initialized(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
while !is.eof()? {
|
||||||
|
let (field_number, wire_type) = is.read_tag_unpack()?;
|
||||||
|
match field_number {
|
||||||
|
1 => {
|
||||||
|
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||||
|
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||||
|
}
|
||||||
|
let tmp = is.read_uint64()?;
|
||||||
|
self.blockHeight = tmp;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.txHash)?;
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||||
|
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||||
|
}
|
||||||
|
let tmp = is.read_uint64()?;
|
||||||
|
self.value = tmp;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute sizes of nested messages
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn compute_size(&self) -> u32 {
|
||||||
|
let mut my_size = 0;
|
||||||
|
if self.blockHeight != 0 {
|
||||||
|
my_size += ::protobuf::rt::value_size(1, self.blockHeight, ::protobuf::wire_format::WireTypeVarint);
|
||||||
|
}
|
||||||
|
if !self.txHash.is_empty() {
|
||||||
|
my_size += ::protobuf::rt::bytes_size(2, &self.txHash);
|
||||||
|
}
|
||||||
|
if self.value != 0 {
|
||||||
|
my_size += ::protobuf::rt::value_size(3, self.value, ::protobuf::wire_format::WireTypeVarint);
|
||||||
|
}
|
||||||
|
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||||
|
self.cached_size.set(my_size);
|
||||||
|
my_size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
if self.blockHeight != 0 {
|
||||||
|
os.write_uint64(1, self.blockHeight)?;
|
||||||
|
}
|
||||||
|
if !self.txHash.is_empty() {
|
||||||
|
os.write_bytes(2, &self.txHash)?;
|
||||||
|
}
|
||||||
|
if self.value != 0 {
|
||||||
|
os.write_uint64(3, self.value)?;
|
||||||
|
}
|
||||||
|
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cached_size(&self) -> u32 {
|
||||||
|
self.cached_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
|
||||||
|
&self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
|
||||||
|
&mut self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &::std::any::Any {
|
||||||
|
self as &::std::any::Any
|
||||||
|
}
|
||||||
|
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
|
||||||
|
self as &mut ::std::any::Any
|
||||||
|
}
|
||||||
|
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
Self::descriptor_static()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new() -> ValueReceived {
|
||||||
|
ValueReceived::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
|
||||||
|
lock: ::protobuf::lazy::ONCE_INIT,
|
||||||
|
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
descriptor.get(|| {
|
||||||
|
let mut fields = ::std::vec::Vec::new();
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>(
|
||||||
|
"blockHeight",
|
||||||
|
|m: &ValueReceived| { &m.blockHeight },
|
||||||
|
|m: &mut ValueReceived| { &mut m.blockHeight },
|
||||||
|
));
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
|
||||||
|
"txHash",
|
||||||
|
|m: &ValueReceived| { &m.txHash },
|
||||||
|
|m: &mut ValueReceived| { &mut m.txHash },
|
||||||
|
));
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint64>(
|
||||||
|
"value",
|
||||||
|
|m: &ValueReceived| { &m.value },
|
||||||
|
|m: &mut ValueReceived| { &mut m.value },
|
||||||
|
));
|
||||||
|
::protobuf::reflect::MessageDescriptor::new::<ValueReceived>(
|
||||||
|
"ValueReceived",
|
||||||
|
fields,
|
||||||
|
file_descriptor_proto()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_instance() -> &'static ValueReceived {
|
||||||
|
static mut instance: ::protobuf::lazy::Lazy<ValueReceived> = ::protobuf::lazy::Lazy {
|
||||||
|
lock: ::protobuf::lazy::ONCE_INIT,
|
||||||
|
ptr: 0 as *const ValueReceived,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
instance.get(ValueReceived::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Clear for ValueReceived {
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.clear_blockHeight();
|
||||||
|
self.clear_txHash();
|
||||||
|
self.clear_value();
|
||||||
|
self.unknown_fields.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for ValueReceived {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
::protobuf::text_format::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::reflect::ProtobufValue for ValueReceived {
|
||||||
|
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
|
||||||
|
::protobuf::reflect::ProtobufValueRef::Message(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
|
\n\x13ValueReceived.proto\x12\x17cash.z.wallet.sdk.proto\"O\n\rValueRece\
|
||||||
|
ived\x12\x17\n\x0bblockHeight\x18\x01\x20\x01(\x04B\x02\x18\0\x12\x12\n\
|
||||||
|
\x06txHash\x18\x02\x20\x01(\x0cB\x02\x18\0\x12\x11\n\x05value\x18\x03\
|
||||||
|
\x20\x01(\x04B\x02\x18\0B\0b\x06proto3\
|
||||||
|
";
|
||||||
|
|
||||||
|
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
|
||||||
|
lock: ::protobuf::lazy::ONCE_INIT,
|
||||||
|
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
|
||||||
|
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
|
||||||
|
unsafe {
|
||||||
|
file_descriptor_proto_lazy.get(|| {
|
||||||
|
parse_descriptor_proto()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue