Merge pull request #218 from zcash/feature/autoshielding-poc

Feature/autoshielding poc
This commit is contained in:
Kevin Gorham 2021-04-22 19:06:02 -04:00 committed by GitHub
commit 5c57b0808f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
173 changed files with 3356 additions and 1879 deletions

2
.gitignore vendored
View File

@ -75,4 +75,4 @@ fraget/
# other
DecompileChecker.kt
backup-dbs/
*.db

401
Cargo.lock generated
View File

@ -17,34 +17,33 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aes"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd2bc6d3f370b5666245ff421e231cba4353df936e26986d2918e61a8fd6aef6"
checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
dependencies = [
"aes-soft",
"aesni",
"block-cipher",
"cipher",
]
[[package]]
name = "aes-soft"
version = "0.5.0"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63dd91889c49327ad7ef3b500fd1109dbd3c509a03db0d4a9ce413b79f575cb6"
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
dependencies = [
"block-cipher",
"byteorder",
"opaque-debug 0.3.0",
"cipher",
"opaque-debug",
]
[[package]]
name = "aesni"
version = "0.8.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6fe808308bb07d393e2ea47780043ec47683fcf19cf5efc8ca51c50cc8c68a"
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
dependencies = [
"block-cipher",
"opaque-debug 0.3.0",
"cipher",
"opaque-debug",
]
[[package]]
@ -134,12 +133,6 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
name = "base64"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
[[package]]
name = "base64"
version = "0.13.0"
@ -148,9 +141,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bech32"
version = "0.7.3"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1"
checksum = "6c7f7096bc256f5e5cb960f60dfc4f4ef979ca65abe7fb9d5a4f77150d3783d4"
[[package]]
name = "bellman"
@ -158,7 +151,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7089887635778eabf0038a166f586eee5413fb85c8fa6c9a754914f0f644f49f"
dependencies = [
"bitvec",
"bitvec 0.18.5",
"blake2s_simd",
"byteorder",
"crossbeam",
@ -185,7 +178,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa"
dependencies = [
"funty",
"radium",
"radium 0.3.0",
"wyz",
]
[[package]]
name = "bitvec"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
dependencies = [
"funty",
"radium 0.5.3",
"tap",
"wyz",
]
@ -211,53 +216,23 @@ dependencies = [
"constant_time_eq",
]
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding 0.1.5",
"byte-tools",
"byteorder",
"generic-array 0.12.4",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array 0.14.4",
]
[[package]]
name = "block-cipher"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f337a3e6da609650eb74e02bc9fac7b735049f7623ab12f2e4c719316fcc7e80"
dependencies = [
"generic-array 0.14.4",
"generic-array",
]
[[package]]
name = "block-modes"
version = "0.6.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9b14fd8a4739e6548d4b6018696cf991dcf8c6effd9ef9eb33b29b8a650972"
checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
dependencies = [
"block-cipher",
"block-padding 0.2.1",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
"block-padding",
"cipher",
]
[[package]]
@ -272,7 +247,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4caf0101205582491f772d60a6fcb6bcec19963e68209cb631851eeadb01421f"
dependencies = [
"bitvec",
"bitvec 0.18.5",
"ff",
"group",
"pairing",
@ -282,11 +257,11 @@ dependencies = [
[[package]]
name = "bs58"
version = "0.3.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
dependencies = [
"sha2 0.8.2",
"sha2",
]
[[package]]
@ -295,12 +270,6 @@ version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.4.3"
@ -343,6 +312,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
dependencies = [
"generic-array",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
@ -364,9 +342,9 @@ dependencies = [
[[package]]
name = "const_fn"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
checksum = "076a6803b0dacd6a88cfe64deba628b01533ff5ef265687e6938280c1afd0a28"
[[package]]
name = "constant_time_eq"
@ -478,22 +456,13 @@ dependencies = [
"crypto_api",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array 0.12.4",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array 0.14.4",
"generic-array",
]
[[package]]
@ -535,7 +504,7 @@ dependencies = [
[[package]]
name = "equihash"
version = "0.1.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#4253f8ef810d199bef0808a6fe3fbf809a5558c8"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"blake2b_simd",
"byteorder",
@ -572,12 +541,6 @@ dependencies = [
"synstructure",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
@ -596,16 +559,16 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef"
dependencies = [
"bitvec",
"bitvec 0.18.5",
"rand_core 0.5.1",
"subtle",
]
[[package]]
name = "fpe"
version = "0.3.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef2196a22f6d98bbde79ae510eb4f397bd446cfbd6c26425e25ec81442a31bab"
checksum = "a25080721bbcd2cd4d765b7d607ea350425fa087ce53cd3e31afcacdab850352"
dependencies = [
"aes",
"block-modes",
@ -650,9 +613,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
[[package]]
name = "futures"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
dependencies = [
"futures-channel",
"futures-core",
@ -665,9 +628,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
dependencies = [
"futures-core",
"futures-sink",
@ -675,9 +638,9 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
[[package]]
name = "futures-cpupool"
@ -691,9 +654,9 @@ dependencies = [
[[package]]
name = "futures-executor"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
dependencies = [
"futures-core",
"futures-task",
@ -702,15 +665,15 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
[[package]]
name = "futures-macro"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
dependencies = [
"proc-macro-hack",
"proc-macro2",
@ -720,21 +683,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
[[package]]
name = "futures-task"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
[[package]]
name = "futures-util"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
dependencies = [
"futures-channel",
"futures-core",
@ -750,15 +713,6 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
@ -806,7 +760,7 @@ checksum = "f61e21f9181e4f3732976a62a81f2b53f1195867d99325b5b9408b19219137e2"
dependencies = [
"base64 0.9.3",
"bytes 0.5.6",
"futures 0.3.13",
"futures 0.3.14",
"httpbis",
"log",
"log-ndc",
@ -855,6 +809,18 @@ dependencies = [
"secp256k1",
]
[[package]]
name = "hdwallet"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2033326faddc94885c26775db24683819bf3ae9461e016c45df18b910bdeedd7"
dependencies = [
"lazy_static",
"rand_core 0.6.2",
"ring",
"secp256k1",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
@ -877,7 +843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3e4404f8f87938a2db89336609bde64363f5a556b15af936343e7252c9648d"
dependencies = [
"bytes 0.5.6",
"futures 0.3.13",
"futures 0.3.14",
"log",
"log-ndc",
"net2",
@ -926,9 +892,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.48"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
dependencies = [
"wasm-bindgen",
]
@ -939,7 +905,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "620638af3b80d23f4df0cae21e3cc9809ac8826767f345066f010bcea66a2c55"
dependencies = [
"bitvec",
"bitvec 0.18.5",
"bls12_381",
"ff",
"group",
@ -978,9 +944,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.88"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
[[package]]
name = "libsqlite3-sys"
@ -1106,10 +1072,12 @@ dependencies = [
[[package]]
name = "nom"
version = "5.1.2"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [
"bitvec 0.19.5",
"funty",
"lexical-core",
"memchr",
"version_check",
@ -1167,12 +1135,6 @@ version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "opaque-debug"
version = "0.3.0"
@ -1239,36 +1201,36 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
[[package]]
name = "protobuf"
version = "2.22.0"
version = "2.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f72884896d22e0da0e5b266cb9a780b791f6c3b2f5beab6368d6cd4f0dbb86"
checksum = "1b7f4a129bb3754c25a4e04032a90173c68f85168f77118ac4cb4936e7f06f92"
dependencies = [
"bytes 1.0.1",
]
[[package]]
name = "protobuf-codegen"
version = "2.22.0"
version = "2.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8217a1652dbc91d19c509c558234145faed729191a966896414e5889f62d543"
checksum = "e5d2fa3a461857508103b914da60dd7b489c1a834967c2e214ecc1496f0c486a"
dependencies = [
"protobuf",
]
[[package]]
name = "protobuf-codegen-pure"
version = "2.22.0"
version = "2.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f239d71417bdc5f8d83c07aeb265f911346e5540a1a6c4285f9c3d1966ed6e3"
checksum = "b3a2520307dbb0df861ed77603770dc23b0ec15e5048272416d6447de98e862b"
dependencies = [
"protobuf",
"protobuf-codegen",
@ -1289,6 +1251,12 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.5.6"
@ -1383,21 +1351,20 @@ dependencies = [
[[package]]
name = "regex"
version = "1.4.3"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.22"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "ring"
@ -1420,9 +1387,9 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251"
dependencies = [
"block-buffer 0.9.0",
"digest 0.9.0",
"opaque-debug 0.3.0",
"block-buffer",
"digest",
"opaque-debug",
]
[[package]]
@ -1510,9 +1477,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
dependencies = [
"ring",
"untrusted",
@ -1553,15 +1520,15 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.124"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
[[package]]
name = "serde_derive"
version = "1.0.124"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2",
"quote",
@ -1585,29 +1552,17 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
[[package]]
name = "sha2"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
dependencies = [
"block-buffer 0.7.3",
"digest 0.8.1",
"fake-simd",
"opaque-debug 0.2.3",
]
[[package]]
name = "sha2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
dependencies = [
"block-buffer 0.9.0",
"block-buffer",
"cfg-if 1.0.0",
"cpuid-bool",
"digest 0.9.0",
"opaque-debug 0.3.0",
"digest",
"opaque-debug",
]
[[package]]
@ -1630,9 +1585,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "standback"
version = "0.2.15"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2beb4d1860a61f571530b3f855a1b538d0200f7871c63331ecd6f17b1f014f8"
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
dependencies = [
"version_check",
]
@ -1700,9 +1655,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]]
name = "syn"
version = "1.0.63"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717"
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
dependencies = [
"proc-macro2",
"quote",
@ -1722,19 +1677,16 @@ dependencies = [
]
[[package]]
name = "thread_local"
version = "1.1.3"
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "time"
version = "0.2.25"
version = "0.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1195b046942c221454c2539395f85413b33383a067449d78aab2b7b052a142f7"
checksum = "08a8cbfbf47955132d0202d1662f49b2423ae35862aee471f3ba4b133358f372"
dependencies = [
"const_fn",
"libc",
@ -1821,9 +1773,9 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.12.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]]
name = "unicode-xid"
@ -1849,15 +1801,15 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "vcpkg"
version = "0.2.11"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
[[package]]
name = "version_check"
version = "0.9.2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
@ -1867,9 +1819,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "walkdir"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi 0.3.9",
@ -1884,9 +1836,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasm-bindgen"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -1894,9 +1846,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
dependencies = [
"bumpalo",
"lazy_static",
@ -1909,9 +1861,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1919,9 +1871,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
dependencies = [
"proc-macro2",
"quote",
@ -1932,15 +1884,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
[[package]]
name = "web-sys"
version = "0.3.48"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -2031,10 +1983,10 @@ dependencies = [
"android_logger",
"bls12_381",
"failure",
"futures 0.3.13",
"futures 0.3.14",
"grpc",
"grpc-protobuf",
"hdwallet",
"hdwallet 0.2.5",
"hex",
"httpbis",
"jni",
@ -2052,18 +2004,19 @@ dependencies = [
[[package]]
name = "zcash_client_backend"
version = "0.4.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#4253f8ef810d199bef0808a6fe3fbf809a5558c8"
version = "0.5.0"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"base64 0.12.3",
"base64 0.13.0",
"bech32",
"bls12_381",
"bs58",
"ff",
"group",
"hdwallet",
"hdwallet 0.3.0",
"hex",
"jubjub",
"log",
"nom",
"percent-encoding",
"protobuf",
@ -2071,16 +2024,17 @@ dependencies = [
"rand_core 0.5.1",
"ripemd160",
"secp256k1",
"sha2 0.9.3",
"sha2",
"subtle",
"time",
"zcash_note_encryption",
"zcash_primitives",
]
[[package]]
name = "zcash_client_sqlite"
version = "0.2.1"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#4253f8ef810d199bef0808a6fe3fbf809a5558c8"
version = "0.3.0"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"bech32",
"bs58",
@ -2090,18 +2044,33 @@ dependencies = [
"protobuf",
"rand_core 0.5.1",
"rusqlite",
"secp256k1",
"time",
"zcash_client_backend",
"zcash_primitives",
]
[[package]]
name = "zcash_note_encryption"
version = "0.0.0"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"blake2b_simd",
"byteorder",
"crypto_api_chachapoly",
"ff",
"group",
"rand_core 0.5.1",
"subtle",
]
[[package]]
name = "zcash_primitives"
version = "0.4.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#4253f8ef810d199bef0808a6fe3fbf809a5558c8"
version = "0.5.0"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"aes",
"bitvec",
"bitvec 0.18.5",
"blake2b_simd",
"blake2s_simd",
"bls12_381",
@ -2110,6 +2079,7 @@ dependencies = [
"equihash",
"ff",
"fpe",
"funty",
"group",
"hex",
"jubjub",
@ -2119,14 +2089,15 @@ dependencies = [
"rand_core 0.5.1",
"ripemd160",
"secp256k1",
"sha2 0.9.3",
"sha2",
"subtle",
"zcash_note_encryption",
]
[[package]]
name = "zcash_proofs"
version = "0.4.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#4253f8ef810d199bef0808a6fe3fbf809a5558c8"
version = "0.5.0"
source = "git+https://github.com/gmale/librustzcash?branch=autoshield-poc-daa-taddr3#74434f370cf474156b73bfb685cb62e8cd5bcd42"
dependencies = [
"bellman",
"blake2b_simd",

View File

@ -16,10 +16,10 @@ hex = "0.4"
jni = { version = "0.17", default-features = false }
log = "0.4"
log-panics = "2.0.0"
zcash_client_backend = "0.4"
zcash_client_sqlite = "0.2.1"
zcash_primitives = "0.4"
zcash_proofs = "0.4"
zcash_client_backend = "0.5"
zcash_client_sqlite = "0.3"
zcash_primitives = "0.5"
zcash_proofs = "0.5"
#### Temporary additions: ####################################
#base58 = "0.1.0"
@ -50,7 +50,7 @@ protobuf-codegen-pure = "2.14"
#zcash_primitives = { git = 'https://github.com/zcash/librustzcash.git', rev='04a2bd4ad86980e0c2862706bd402b85b9dd1965' }
#zcash_proofs = { git = 'https://github.com/zcash/librustzcash.git', rev='04a2bd4ad86980e0c2862706bd402b85b9dd1965' }
# Uncomment this to test librustzcash changes locally
## Uncomment this to test librustzcash changes locally
#[patch.crates-io]
#zcash_client_backend = { path = '../../clones/librustzcash/zcash_client_backend' }
#zcash_client_sqlite = { path = '../../clones/librustzcash/zcash_client_sqlite' }
@ -59,14 +59,14 @@ protobuf-codegen-pure = "2.14"
# Uncomment this to test someone else's librustzcash changes in a branch
[patch.crates-io]
zcash_client_backend = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa"}
zcash_client_sqlite = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa"}
zcash_primitives = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa"}
zcash_proofs = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa"}
zcash_client_backend = {git = "https://github.com/gmale/librustzcash", branch = "autoshield-poc-daa-taddr3"}
zcash_client_sqlite = {git = "https://github.com/gmale/librustzcash", branch = "autoshield-poc-daa-taddr3"}
zcash_primitives = {git = "https://github.com/gmale/librustzcash", branch = "autoshield-poc-daa-taddr3"}
zcash_proofs = {git = "https://github.com/gmale/librustzcash", branch = "autoshield-poc-daa-taddr3"}
[features]
mainnet = ["zcash_client_sqlite/mainnet", "zcash_client_sqlite/transparent-inputs", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
testnet = ["zcash_client_backend/transparent-inputs", "zcash_client_sqlite/transparent-inputs", "zcash_primitives/transparent-inputs"]
mainnet = ["zcash_client_sqlite/mainnet"]
testnet = []
updater = ["bls12_381", "futures", "grpc", "grpc-protobuf", "httpbis", "tls-api", "tls-api-rustls"]
[lib]

View File

@ -22,10 +22,12 @@ This lightweight SDK connects Android to Zcash. It welds together Rust and Kotli
## Contents
- [Requirements](#requirements)
- [Structure](#structure)
- [Overview](#overview)
- [Components](#components)
- [Quickstart](#quickstart)
- [Examples](#examples)
- [Compiling Sources](#compiling-sources)
- [Versioning](#versioning)
- [Examples](#examples)
@ -126,6 +128,26 @@ Send funds to another address
synchronizer.sendToAddress(spendingKey, zatoshi, address, memo)
```
[Back to contents](#contents)
## Examples
Full working examples can be found in the [demo app](https://github.com/zcash/zcash-android-wallet-sdk/tree/master/samples/demo-app), covering all major functionality of the SDK. Each demo strives to be self-contained so that a developer can understand everything required for it to work. Testnet builds of the demo app will soon be available to [download as github releases](https://github.com/zcash/zcash-android-wallet-sdk/releases).
### Demos
Menu Item|Related Code|Description
:-----|:-----|:-----
Get Private Key|[GetPrivateKeyFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getprivatekey/GetPrivateKeyFragment.kt)|Given a seed, display its viewing key and spending key
Get Address|[GetAddressFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getaddress/GetAddressFragment.kt)|Given a seed, display its z-addr
Get Balance|[GetBalanceFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getbalance/GetBalanceFragment.kt)|Display the balance
Get Latest Height|[GetLatestHeightFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getlatestheight/GetLatestHeightFragment.kt)|Given a lightwalletd server, retrieve the latest block height
Get Block|[GetBlockFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getblock/GetBlockFragment.kt)|Given a lightwalletd server, retrieve a compact block
Get Block Range|[GetBlockRangeFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/getblockrange/GetBlockRangeFragment.kt)|Given a lightwalletd server, retrieve a range of compact blocks
List Transactions|[ListTransactionsFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/listtransactions/ListTransactionsFragment.kt)|Given a seed, list all related shielded transactions
Send|[SendFragment.kt](app/src/main/java/cash/z/ecc/android/sdk/demoapp/demos/send/SendFragment.kt)|Send and monitor a transaction, the most complex demo
[Back to contents](#contents)
## Compiling Sources

View File

@ -1,23 +1,16 @@
import cash.z.ecc.android.Deps
loadConfig('config.gradle')
// Publishing settings
project.group = config.publish.group
project.version = config.publish.versionName
project.ext.POM_ARTIFACT_ID = config.publish.artifactId
buildscript {
ext.buildConfig = [
'compileSdkVersion': 30,
'minSdkVersion': 16,
'targetSdkVersion': 30
]
ext.versions = [
'architectureComponents': [
'lifecycle': '2.2.0',
'room': '2.2.5',
'paging': '2.1.2'
],
'grpc':'1.34.1',
'coroutines': '1.4.2',
'junitJupiter': '5.6.1'
]
ext.kotlinVersion = '1.4.31'
repositories {
mavenLocal()
google()
mavenCentral()
jcenter()
maven {
url 'https://jitpack.io'
@ -27,43 +20,30 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
classpath "org.jetbrains.kotlin:kotlin-allopen:${Deps.kotlinVersion}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1"
classpath "com.github.ben-manes:gradle-versions-plugin:0.31.0"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.android.tools.build:gradle:4.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.30"
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.14"
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:1.0.2'
classpath 'com.github.str4d:rust-android-gradle:68b4ecc053'
classpath 'org.owasp:dependency-check-gradle:6.0.0'
classpath "gradle.plugin.com.dorongold.plugins:task-tree:1.5"
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.14.2'
}
}
apply from: 'custom-tasks.gradle'
apply from: "$rootDir/ktlint.gradle"
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-allopen'
apply plugin: 'org.jetbrains.dokka'
apply plugin: 'com.google.protobuf'
apply plugin: 'com.github.ben-manes.versions'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.getkeepsafe.dexcount'
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
apply plugin: 'org.owasp.dependencycheck'
apply plugin: "com.dorongold.task-tree"
apply from: 'ci.gradle'
apply from: 'publish.gradle'
apply plugin: 'com.vanniktech.maven.publish'
//apply from: 'ci.gradle'
group = Deps.group
version = Deps.versionName
repositories {
google()
@ -72,21 +52,21 @@ repositories {
}
android {
compileSdkVersion buildConfig.compileSdkVersion
compileSdkVersion config.compileSdkVersion
useLibrary 'android.test.runner'
ndkVersion "21.1.6352462"
defaultConfig {
minSdkVersion buildConfig.minSdkVersion
targetSdkVersion buildConfig.targetSdkVersion
versionCode = Deps.versionCode
versionName = Deps.versionName
minSdkVersion config.minSdkVersion
targetSdkVersion config.targetSdkVersion
versionCode = config.publish.versionCode
versionName = config.publish.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
multiDexEnabled true
archivesBaseName = "zcash-android-sdk-${Deps.versionName}"
archivesBaseName = "zcash-android-sdk-${config.publish.name}"
javaCompileOptions {
annotationProcessorOptions {
@ -109,19 +89,6 @@ android {
}
}
flavorDimensions 'network'
productFlavors {
// would rather name them "testnet" and "mainnet" but product flavor names cannot start with the word "test"
zcashtestnet {
dimension 'network'
}
zcashmainnet {
dimension 'network'
}
}
sourceSets {
main {
java {
@ -157,6 +124,9 @@ android {
exclude 'META-INF/LICENSE-notice.md'
}
}
mavenPublish {
androidVariantToPublish = config.publish.target
}
allOpen {
// marker for classes that we want to be able to extend in debug builds for testing purposes
@ -167,16 +137,23 @@ clean {
delete "$project.projectDir/src/generated/source/grpc"
}
dokka {
outputFormat = 'html'
outputDirectory = "$buildDir/docs/rtd"
dokkaHtml.configure {
dokkaSourceSets {
configureEach {
outputDirectory.set(file("build/docs/rtd"))
displayName.set("Zcash Android SDK")
includes.from("packages.md")
// samples.from("samples/basic.kt", "samples/advanced.kt")
}
}
}
protobuf {
generatedFilesBaseDir = "$projectDir/src/generated/source/grpc"
protoc { artifact = 'com.google.protobuf:protoc:3.14.0' }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${versions.grpc}" }
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.37.0" }
}
generateProtoTasks {
all().each { task ->
@ -206,53 +183,44 @@ cargo {
profile = "release"
forceTargets = true
prebuiltToolchains = true
variants {
zcashmainnetDebug {
defaultFeaturesAnd("mainnet")
}
zcashmainnetRelease {
defaultFeaturesAnd("mainnet")
}
zcashtestnetDebug {
defaultFeaturesAnd("testnet")
}
zcashtestnetRelease {
defaultFeaturesAnd("testnet")
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
implementation AndroidX.appCompat
// Architecture Components: Lifecycle
implementation "androidx.lifecycle:lifecycle-runtime:${versions.architectureComponents.lifecycle}"
implementation "androidx.lifecycle:lifecycle-extensions:${versions.architectureComponents.lifecycle}"
implementation "androidx.lifecycle:lifecycle-common-java8:${versions.architectureComponents.lifecycle}"
implementation AndroidX.lifecycle.runtimeKtx
implementation AndroidX.lifecycle.commonJava8
// Architecture Components: Room
implementation "androidx.room:room-runtime:${versions.architectureComponents.room}"
implementation "androidx.room:room-common:${versions.architectureComponents.room}"
implementation "androidx.room:room-ktx:${versions.architectureComponents.room}"
implementation "androidx.paging:paging-runtime-ktx:${versions.architectureComponents.paging}"
kapt "androidx.room:room-compiler:${versions.architectureComponents.room}"
implementation AndroidX.room.runtime
implementation AndroidX.room.common
implementation AndroidX.room.ktx
implementation AndroidX.room.compiler
implementation AndroidX.paging.runtimeKtx
kapt AndroidX.room.compiler
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Deps.kotlinVersion}"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}"
implementation Kotlin.stdlib.jdk8
implementation KotlinX.coroutines.core
implementation KotlinX.coroutines.android
// grpc-java
implementation "io.grpc:grpc-okhttp:${versions.grpc}"
implementation "io.grpc:grpc-android:${versions.grpc}"
implementation "io.grpc:grpc-protobuf-lite:${versions.grpc}"
implementation "io.grpc:grpc-stub:${versions.grpc}"
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
implementation "io.grpc:grpc-okhttp:_"
implementation "io.grpc:grpc-android:_"
implementation "io.grpc:grpc-protobuf-lite:_"
implementation "io.grpc:grpc-stub:_"
compileOnly 'javax.annotation:javax.annotation-api:_'
//
// Locked Versions
// these should be checked regularly and removed when possible
// solves error: Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-26.0-android.jar (com.google.guava:guava:26.0-android) and listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0)
// per this recommendation from Chris Povirk, given guava's decision to split ListenableFuture away from Guava: https://groups.google.com/d/msg/guava-discuss/GghaKwusjcY/bCIAKfzOEwAJ
implementation 'com.google.guava:guava:30.0-android'
// Transitive dependencies used because they're already necessary for other libraries
// GSON is available as a transitive dependency from several places so we use it for processing
// checkpoints but also document that by explicitly including here. If dependencies like Room
@ -260,18 +228,18 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
// OKIO is a transitive dependency used when writing param files to disk. Like GSON, this can be
// replaced if needed. For compatibility, we match the library version used in grpc-okhttp:
// https://github.com/grpc/grpc-java/blob/v1.34.x/build.gradle#L154
implementation 'com.squareup.okio:okio:1.13.0'
// https://github.com/grpc/grpc-java/blob/v1.37.x/build.gradle#L159
implementation 'com.squareup.okio:okio:1.17.5'
// Tests
testImplementation 'androidx.multidex:multidex:2.0.1'
testImplementation "org.jetbrains.kotlin:kotlin-reflect:${Deps.kotlinVersion}"
testImplementation "org.jetbrains.kotlin:kotlin-reflect:_"
testImplementation 'org.mockito:mockito-junit-jupiter:3.5.10'
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0'
testImplementation "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}"
testImplementation "org.junit.jupiter:junit-jupiter-engine:${versions.junitJupiter}"
testImplementation "org.junit.jupiter:junit-jupiter-migrationsupport:${versions.junitJupiter}"
testImplementation "io.grpc:grpc-testing:${versions.grpc}"
testImplementation "org.junit.jupiter:junit-jupiter-api:_"
testImplementation "org.junit.jupiter:junit-jupiter-engine:_"
testImplementation "org.junit.jupiter:junit-jupiter-migrationsupport:_"
testImplementation "io.grpc:grpc-testing:_"
// NOTE: androidTests will use JUnit4, while src/test/java tests will leverage Junit5
// Attempting to use JUnit5 via https://github.com/mannodermaus/android-junit5 was painful. The plugin configuration
@ -280,21 +248,24 @@ dependencies {
androidTestImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0'
androidTestImplementation 'org.mockito:mockito-android:3.5.10'
androidTestImplementation "androidx.test:runner:1.3.0"
androidTestImplementation 'com.android.support:support-annotations:28.0.0'
androidTestImplementation "androidx.test:core:1.3.0"
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0'
// used by 'ru.gildor.coroutines.okhttp.await' (to make simple suspended requests) and breaks on versions higher than 3.8.0
androidTestImplementation "com.squareup.okhttp3:okhttp:3.8.0"
// sample mnemonic plugin
androidTestImplementation 'com.github.zcash:zcash-android-wallet-plugins:1.0.1'
androidTestImplementation 'cash.z.ecc.android:kotlin-bip39:1.0.1'
androidTestImplementation 'cash.z.ecc.android:kotlin-bip39:1.0.2'
}
taskTree{
noRepeat = true //do not print a sub-tree in the task-tree more than once
impliesSubProjects = true //do not print task-tree for child projects in a multi-project
taskDepth = 2 // limit tree depth to 3. Equivalent to running with the --task-depth option.
}
//taskTree{
// noRepeat = true //do not print a sub-tree in the task-tree more than once
// impliesSubProjects = true //do not print task-tree for child projects in a multi-project
// taskDepth = 2 // limit tree depth to 3. Equivalent to running with the --task-depth option.
//}
defaultTasks 'ciBuild'
@ -302,4 +273,9 @@ preBuild.dependsOn('ktlintFormat')
preBuild.dependsOn('ktlint')
preBuild.dependsOn includeDirBugFix
check.dependsOn dependencyCheckAggregate
//check.dependsOn dependencyCheckAggregate
def loadConfig(fileName) {
def config = new ConfigSlurper().parse(file(fileName).toURL())
project.ext.config = config
}

View File

@ -1,7 +0,0 @@
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}

View File

@ -1,37 +0,0 @@
package cash.z.ecc.android
object Deps {
// For use in the top-level build.gradle which gives an error when provided
// `Deps.Kotlin.version` directly
const val kotlinVersion = "1.4.21"
const val group = "cash.z.ecc.android"
const val artifactName = "zcash-android-sdk"
const val versionName = "1.2.1-beta05"
const val versionCode = 1_02_01_105 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
const val description = "This lightweight SDK connects Android to Zcash. It welds together Rust and Kotlin in a minimal way, allowing third-party Android apps to send and receive shielded transactions easily, securely and privately."
const val githubUrl = "https://github.com/zcash/zcash-android-wallet-sdk"
// publishing
// NOTE: to upload run: ./gradlew bintrayUpload after setting BINTRAY_USER and BINTRAY_API_KEY as environment variable
// to publish for local development run: ./gradlew publishToMavenLocal
// Remember: publish both mainnet and testnet!
const val publishingDryRun = true
val publishingTarget = Publication.Testnet
object Publication {
object Mainnet {
const val variant = "zcashmainnetRelease"
const val artifactId = "zcash-android-sdk-mainnet"
}
object Testnet {
const val variant = "zcashtestnetRelease"
const val artifactId = "zcash-android-sdk-testnet"
}
}
object Kotlin : Version(kotlinVersion) {
val STDLIB = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
}
}
open class Version(@JvmField val version: String)

16
config.gradle Normal file
View File

@ -0,0 +1,16 @@
/////////////////////////////////////////
// Publishing
/////////////////////////////////////////
// general
compileSdkVersion = 30
minSdkVersion = 16
targetSdkVersion = 30
publish {
group = 'cash.z.ecc.android'
versionName = '1.3.0-beta04'
versionCode = 1_03_00_204 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
artifactId = 'zcash-android-sdk'
target = 'release'
}

View File

@ -5,21 +5,3 @@ tasks.register("includeDirBugFix") {
mkdir(protoIncludeDir)
}
}
tasks.register("updateDocs", Copy) {
dependsOn dokka
from("$buildDir/docs/zcash-android-wallet-sdk/cash.z.ecc.android.sdk.data/") {
include '-synchronizer/'
include '-sdk-synchronizer/'
include '-mock-synchronizer/'
include '-twig/'
rename 'index.md', 'README.md'
}
from("$buildDir/docs/zcash-android-wallet-sdk/cash.z.ecc.android.sdk.secure/") {
include '-wallet/'
rename 'index.md', 'README.md'
}
into "docs"
includeEmptyDirs = false
}

View File

@ -19,4 +19,18 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.enableR8=false
# Publishing Constants
POM_NAME=Zcash Android Wallet SDK
POM_DESCRIPTION=This lightweight SDK connects Android to Zcash. It welds together Rust and Kotlin in a minimal way, allowing third-party Android apps to send and receive shielded transactions easily, securely and privately.
POM_INCEPTION_YEAR=2018
POM_URL=https://github.com/zcash/zcash-android-wallet-sdk/
POM_SCM_URL=https://github.com/zcash/zcash-android-wallet-sdk/
POM_SCM_CONNECTION=scm:git:git://github.com/zcash/zcash-android-wallet-sdk.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/zcash/zcash-android-wallet-sdk.git
POM_LICENCE_NAME=The MIT License
POM_LICENCE_URL=http://opensource.org/licenses/MIT
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=gmale
POM_DEVELOPER_NAME=Kevin Gorham
POM_DEVELOPER_URL=https://github.com/gmale/

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip

7
packages.md Normal file
View File

@ -0,0 +1,7 @@
# Module zcash-android-sdk
SDK connecting Android to Zcash. It welds together Rust and Kotlin in a minimal way, allowing third-party Android apps to send and receive shielded transactions easily, securely and privately.
# Package cash.z.ecc.android.sdk.block
Integration tests designed to be executed with darksidewalletd.

View File

@ -1,116 +0,0 @@
import cash.z.ecc.android.Deps
/////////////////////////////////////////
// Publishing
/////////////////////////////////////////
group = Deps.group
version = Deps.versionName
// Create the pom configuration:
def pomConfig = {
licenses {
license {
name "MIT-style"
url "http://opensource.org/licenses/MIT"
distribution "repo"
}
}
developers {
developer {
id "gmale"
name "Kevin Gorham"
email "kevin.gorham@z.cash"
}
}
scm {
url Deps.githubUrl
}
}
// Jar containing Kotlin sources
task sourcesJar(type: Jar) {
archiveClassifier = 'sources'
from kotlin.sourceSets.main.kotlin.srcDirs
}
// Jar containing docs
task docsJar(type: Jar) {
archiveClassifier = "javadoc"
group = JavaBasePlugin.DOCUMENTATION_GROUP
dependsOn dokka
from dokka
}
def activePublication = Deps.publishingTarget
publishing {
publications {
android.libraryVariants.all { variant ->
if (variant.name != activePublication.variant) return
Production(MavenPublication) {
artifact variant.outputs[0].packageLibrary // the AAR
artifact sourcesJar
artifact docsJar
groupId Deps.group
artifactId activePublication.artifactId
version Deps.versionName
pom.withXml {
def root = asNode()
root.appendNode('description', Deps.description)
root.appendNode('name', activePublication.artifactId)
root.appendNode('url', )
root.children().last() + pomConfig
// AAR-specific: we must explicitly add dependencies for an AAR
def depsNode = root["dependencies"][0] ?: root.appendNode("dependencies")
def addDep = {
if (it.group == null) return // Avoid empty dependency nodes
def dependencyNode = depsNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
if (it.hasProperty('type')) {
dependencyNode.appendNode('type', it.type)
}
if (it.hasProperty('scope')) {
dependencyNode.appendNode('scope', it.scope)
}
if (it.hasProperty('optional') && it.optional) {
dependencyNode.appendNode('optional', 'true')
}
}
// run the 'addDep' closure over each dependency
configurations.implementation.allDependencies.each addDep
}
}
}
}
}
bintray {
user = project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER')
key = project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY')
publications = ['Production']
override = true
pkg {
repo = 'android'
name = activePublication.artifactId
description = Deps.description
publish = true
publicDownloadNumbers = true
userOrg = 'ecc-mobile'
labels = ['aar', 'native', 'android', 'zcash', 'ecc', 'sdk', 'kotlin', 'mobile', 'electric coin company', 'open source', 'crypto', 'cryptocurrency', 'cryptography', 'privacy']
licenses = ['MIT']
vcsUrl = Deps.githubUrl
dryRun = Deps.publishingDryRun
version {
name = Deps.versionName
desc = Deps.description
released = new Date()
vcsTag = this.version
}
}
}

View File

@ -2,7 +2,7 @@ package cash.z.ecc.android.sdk.demoapp
data class DemoConfig(
val alias: String = "SdkDemo",
val host: String = "lightwalletd.electriccoin.co",
val host: String = "mainnet.lightwalletd.com",
val port: Int = 9067,
val birthdayHeight: Int = 968000,
val utxoEndHeight: Int = 968085,

View File

@ -2,7 +2,7 @@ package cash.z.ecc.android.sdk.demoapp
data class DemoConfig(
val alias: String = "SdkDemo",
val host: String = "lightwalletd.testnet.electriccoin.co",
val host: String = "testnet.lightwalletd.com",
val port: Int = 9067,
val birthdayHeight: Int = 954_500,
val utxoEndHeight: Int = 1075590,

View File

@ -0,0 +1,425 @@
{
"formatVersion": 1,
"database": {
"version": 7,
"identityHash": "8e6d7ff0e82352e1fa54e951a5006ba9",
"entities": [
{
"tableName": "transactions",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id_tx` INTEGER, `txid` BLOB NOT NULL, `tx_index` INTEGER, `created` TEXT, `expiry_height` INTEGER, `block` INTEGER, `raw` BLOB, PRIMARY KEY(`id_tx`), FOREIGN KEY(`block`) REFERENCES `blocks`(`height`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id_tx",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "transactionId",
"columnName": "txid",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "transactionIndex",
"columnName": "tx_index",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "created",
"columnName": "created",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "expiryHeight",
"columnName": "expiry_height",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "minedHeight",
"columnName": "block",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "raw",
"columnName": "raw",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id_tx"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "blocks",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"block"
],
"referencedColumns": [
"height"
]
}
]
},
{
"tableName": "blocks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`height` INTEGER, `hash` BLOB NOT NULL, `time` INTEGER NOT NULL, `sapling_tree` BLOB NOT NULL, PRIMARY KEY(`height`))",
"fields": [
{
"fieldPath": "height",
"columnName": "height",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "hash",
"columnName": "hash",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "saplingTree",
"columnName": "sapling_tree",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"height"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "received_notes",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id_note` INTEGER, `tx` INTEGER NOT NULL, `output_index` INTEGER NOT NULL, `account` INTEGER NOT NULL, `value` INTEGER NOT NULL, `spent` INTEGER, `diversifier` BLOB NOT NULL, `rcm` BLOB NOT NULL, `nf` BLOB NOT NULL, `is_change` INTEGER NOT NULL, `memo` BLOB, PRIMARY KEY(`id_note`), FOREIGN KEY(`tx`) REFERENCES `transactions`(`id_tx`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`account`) REFERENCES `accounts`(`account`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`spent`) REFERENCES `transactions`(`id_tx`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id_note",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "transactionId",
"columnName": "tx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "outputIndex",
"columnName": "output_index",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "account",
"columnName": "account",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "spent",
"columnName": "spent",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "diversifier",
"columnName": "diversifier",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "rcm",
"columnName": "rcm",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "nf",
"columnName": "nf",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "isChange",
"columnName": "is_change",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "memo",
"columnName": "memo",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id_note"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "transactions",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"tx"
],
"referencedColumns": [
"id_tx"
]
},
{
"table": "accounts",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"account"
],
"referencedColumns": [
"account"
]
},
{
"table": "transactions",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"spent"
],
"referencedColumns": [
"id_tx"
]
}
]
},
{
"tableName": "accounts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account` INTEGER, `extfvk` TEXT NOT NULL, `address` TEXT NOT NULL, `transparent_address` TEXT NOT NULL, PRIMARY KEY(`account`))",
"fields": [
{
"fieldPath": "account",
"columnName": "account",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "extendedFullViewingKey",
"columnName": "extfvk",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "address",
"columnName": "address",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "transparentAddress",
"columnName": "transparent_address",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"account"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "sent_notes",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id_note` INTEGER, `tx` INTEGER NOT NULL, `output_index` INTEGER NOT NULL, `from_account` INTEGER NOT NULL, `address` TEXT NOT NULL, `value` INTEGER NOT NULL, `memo` BLOB, PRIMARY KEY(`id_note`), FOREIGN KEY(`tx`) REFERENCES `transactions`(`id_tx`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`from_account`) REFERENCES `accounts`(`account`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id_note",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "transactionId",
"columnName": "tx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "outputIndex",
"columnName": "output_index",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "account",
"columnName": "from_account",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "address",
"columnName": "address",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "memo",
"columnName": "memo",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id_note"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "transactions",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"tx"
],
"referencedColumns": [
"id_tx"
]
},
{
"table": "accounts",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"from_account"
],
"referencedColumns": [
"account"
]
}
]
},
{
"tableName": "utxos",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id_utxo` INTEGER, `address` TEXT NOT NULL, `prevout_txid` BLOB NOT NULL, `prevout_idx` INTEGER NOT NULL, `script` BLOB NOT NULL, `value_zat` INTEGER NOT NULL, `height` INTEGER NOT NULL, `spent_in_tx` INTEGER, PRIMARY KEY(`id_utxo`), FOREIGN KEY(`spent_in_tx`) REFERENCES `transactions`(`id_tx`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id_utxo",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "address",
"columnName": "address",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "txid",
"columnName": "prevout_txid",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "transactionIndex",
"columnName": "prevout_idx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "script",
"columnName": "script",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value_zat",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "height",
"columnName": "height",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "spent",
"columnName": "spent_in_tx",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id_utxo"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "transactions",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"spent_in_tx"
],
"referencedColumns": [
"id_tx"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8e6d7ff0e82352e1fa54e951a5006ba9')"
]
}
}

View File

@ -1 +1,10 @@
import de.fayard.refreshVersions.RefreshVersionsSetup
buildscript {
repositories { gradlePluginPortal() }
dependencies.classpath("de.fayard.refreshVersions:refreshVersions:0.9.7")
}
RefreshVersionsSetup.bootstrap(settings)
rootProject.name = 'zcash-android-sdk'

View File

@ -1,110 +1,98 @@
package cash.z.ecc.android.sdk
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.exception.InitializerException
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ZcashSdk
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class InitializerTest {
lateinit var initializer: Initializer
@After
fun cleanUp() {
// don't leave databases sitting around after this test is run
if (::initializer.isInitialized) initializer.erase()
}
@Test
fun testInit() {
val height = 980000
initializer = Initializer(context) { config ->
config.importedWalletBirthday(height)
config.setViewingKeys(
"zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
"zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7"
)
config.alias = "VkInitTest1"
}
assertEquals(height, initializer.birthday.height)
initializer.erase()
}
@Test
fun testErase() {
val alias = "VkInitTest2"
initializer = Initializer(context) { config ->
config.importedWalletBirthday(1_419_900)
config.setViewingKeys(
"zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
"zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7"
)
config.alias = alias
}
assertTrue("Failed to erase initializer", Initializer.erase(context, alias))
assertFalse("Expected false when erasing nothing.", Initializer.erase(context))
}
@Test(expected = InitializerException.MissingDefaultBirthdayException::class)
fun testMissingBirthday() {
val config = Initializer.Config { config ->
config.setViewingKeys("vk1")
}
config.validate()
}
@Test(expected = InitializerException.InvalidBirthdayHeightException::class)
fun testOutOfBoundsBirthday() {
val config = Initializer.Config { config ->
config.setViewingKeys("vk1")
config.setBirthdayHeight(ZcashSdk.SAPLING_ACTIVATION_HEIGHT - 1)
}
config.validate()
}
@Test
fun testImportedWalletUsesSaplingActivation() {
initializer = Initializer(context) { config ->
config.setViewingKeys("vk1")
config.importWallet(ByteArray(32))
}
assertEquals("Incorrect height used for import.", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, initializer.birthday.height)
}
@Test
fun testDefaultToOldestHeight_true() {
initializer = Initializer(context) { config ->
config.setViewingKeys("vk1")
config.setBirthdayHeight(null, true)
}
assertEquals("Height should equal sapling activation height when defaultToOldestHeight is true", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, initializer.birthday.height)
}
@Test
fun testDefaultToOldestHeight_false() {
val initialHeight = 750_000
initializer = Initializer(context) { config ->
config.setViewingKeys("vk1")
config.setBirthdayHeight(initialHeight, false)
}
val h = initializer.birthday.height
assertNotEquals("Height should not equal sapling activation height when defaultToOldestHeight is false", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, h)
assertTrue("expected $h to be higher", h >= initialHeight)
}
companion object {
private val context = InstrumentationRegistry.getInstrumentation().context
init {
Twig.plant(TroubleshootingTwig())
}
}
// lateinit var initializer: Initializer
//
// @After
// fun cleanUp() {
// // don't leave databases sitting around after this test is run
// if (::initializer.isInitialized) initializer.erase()
// }
//
// @Test
// fun testInit() {
// val height = 980000
//
// initializer = Initializer(context) { config ->
// config.importedWalletBirthday(height)
// config.setViewingKeys(
// "zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
// "zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7"
// )
// config.alias = "VkInitTest1"
// }
// assertEquals(height, initializer.birthday.height)
// initializer.erase()
// }
//
// @Test
// fun testErase() {
// val alias = "VkInitTest2"
// initializer = Initializer(context) { config ->
// config.importedWalletBirthday(1_419_900)
// config.setViewingKeys(
// "zxviews1qvn6j50dqqqqpqxqkvqgx2sp63jccr4k5t8zefadpzsu0yy73vczfznwc794xz6lvy3yp5ucv43lww48zz95ey5vhrsq83dqh0ky9junq0cww2wjp9c3cd45n5l5x8l2g9atnx27e9jgyy8zasjy26gugjtefphan9al3tx208m8ekev5kkx3ug6pd0qk4gq4j4wfuxajn388pfpq54wklwktqkyjz9e6gam0n09xjc35ncd3yah5aa9ezj55lk4u7v7hn0v86vz7ygq4qj2v",
// "zxviews1qv886f6hqqqqpqy2ajg9sm22vs4gm4hhajthctfkfws34u45pjtut3qmz0eatpqzvllgsvlk3x0y35ktx5fnzqqzueyph20k3328kx46y3u5xs4750cwuwjuuccfp7la6rh8yt2vjz6tylsrwzy3khtjjzw7etkae6gw3vq608k7quka4nxkeqdxxsr9xxdagv2rhhwugs6w0cquu2ykgzgaln2vyv6ah3ram2h6lrpxuznyczt2xl3lyxcwlk4wfz5rh7wzfd7642c2ae5d7"
// )
// config.alias = alias
// }
//
// assertTrue("Failed to erase initializer", Initializer.erase(context, alias))
// assertFalse("Expected false when erasing nothing.", Initializer.erase(context))
// }
//
// @Test(expected = InitializerException.MissingDefaultBirthdayException::class)
// fun testMissingBirthday() {
// val config = Initializer.Config { config ->
// config.setViewingKeys("vk1")
// }
// config.validate()
// }
//
// @Test(expected = InitializerException.InvalidBirthdayHeightException::class)
// fun testOutOfBoundsBirthday() {
// val config = Initializer.Config { config ->
// config.setViewingKeys("vk1")
// config.setBirthdayHeight(ZcashSdk.SAPLING_ACTIVATION_HEIGHT - 1)
// }
// config.validate()
// }
//
// @Test
// fun testImportedWalletUsesSaplingActivation() {
// initializer = Initializer(context) { config ->
// config.setViewingKeys("vk1")
// config.importWallet(ByteArray(32))
// }
// assertEquals("Incorrect height used for import.", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, initializer.birthday.height)
// }
//
// @Test
// fun testDefaultToOldestHeight_true() {
// initializer = Initializer(context) { config ->
// config.setViewingKeys("vk1")
// config.setBirthdayHeight(null, true)
// }
// assertEquals("Height should equal sapling activation height when defaultToOldestHeight is true", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, initializer.birthday.height)
// }
//
// @Test
// fun testDefaultToOldestHeight_false() {
// val initialHeight = 750_000
// initializer = Initializer(context) { config ->
// config.setViewingKeys("vk1")
// config.setBirthdayHeight(initialHeight, false)
// }
// val h = initializer.birthday.height
// assertNotEquals("Height should not equal sapling activation height when defaultToOldestHeight is false", ZcashSdk.SAPLING_ACTIVATION_HEIGHT, h)
// assertTrue("expected $h to be higher", h >= initialHeight)
// }
//
// companion object {
// private val context = InstrumentationRegistry.getInstrumentation().context
// init {
// Twig.plant(TroubleshootingTwig())
// }
// }
}

View File

@ -0,0 +1,29 @@
package cash.z.ecc.android.sdk.annotation
enum class TestPurpose {
/**
* These tests are explicitly designed to preserve behavior that we do not want to lose after
* major upgrades or refactors. It is acceptable for these test to run long and require
* additional infrastructure.
*/
REGRESSION,
/**
* These tests are designed to be run against new pull requests and generally before any changes
* are committed. It is not ideal for these tests to run long.
*/
COMMIT,
/**
* These tests require a running instance of [darksidewalletd](https://github.com/zcash/lightwalletd/blob/master/docs/darksidewalletd.md).
*/
DARKSIDE,
}
/**
* Signals that this test is explicitly intended to be maintained and run regularly in order to
* achieve the given purpose. Eventually, we will run all such tests nightly.
*/
@Target(AnnotationTarget.CLASS)
annotation class MaintainedTest(vararg val purpose: TestPurpose)

View File

@ -3,6 +3,8 @@ package cash.z.ecc.android.sdk.ext
import android.content.Context
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.type.ZcashNetwork
import cash.z.ecc.android.sdk.util.DarksideTestCoordinator
import cash.z.ecc.android.sdk.util.SimpleMnemonics
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@ -12,14 +14,18 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.newFixedThreadPoolContext
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONObject
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import org.junit.BeforeClass
import ru.gildor.coroutines.okhttp.await
import java.util.concurrent.TimeoutException
fun Initializer.Config.seedPhrase(seedPhrase: String) {
setSeed(SimpleMnemonics().toSeed(seedPhrase.toCharArray()))
fun Initializer.Config.seedPhrase(seedPhrase: String, network: ZcashNetwork) {
setSeed(SimpleMnemonics().toSeed(seedPhrase.toCharArray()), network)
}
open class ScopedTest(val defaultTimeout: Long = 2000L) {
@ -93,6 +99,39 @@ open class ScopedTest(val defaultTimeout: Long = 2000L) {
}
}
open class DarksideTest(name: String = javaClass.simpleName) : ScopedTest() {
val sithLord = DarksideTestCoordinator(host = host, port = port)
val validator = sithLord.validator
fun runOnce(block: () -> Unit) {
if (!ranOnce) {
sithLord.enterTheDarkside()
sithLord.synchronizer.start(classScope)
block()
ranOnce = true
}
}
companion object {
// set the host for all tests. Someday, this will need to be set by CI
// so have it read from the environment first and give that precidence
var host = "192.168.1.134"
val port: Int = 9067
private var ranOnce = false
}
}
object BlockExplorer {
suspend fun fetchLatestHeight(): Int {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api.blockchair.com/zcash/blocks?limit=1")
.build()
val result = client.newCall(request).await()
val body = result.body()?.string()
return JSONObject(body).getJSONArray("data").getJSONObject(0).getInt("id")
}
}
object Transactions {
val outbound = arrayOf(
"https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/t-shielded-spend.txt",

View File

@ -0,0 +1,133 @@
package cash.z.ecc.android.sdk.integration
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose
import cash.z.ecc.android.sdk.ext.BlockExplorer
import cash.z.ecc.android.sdk.type.ZcashNetwork
import cash.z.ecc.android.sdk.util.TestWallet
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
/**
* This test is intended to run to make sure that basic things are functional and pinpoint what is
* not working. It was originally developed after a major refactor to find what broke.
*/
@MaintainedTest(TestPurpose.COMMIT)
@RunWith(Parameterized::class)
class SanityTest(
private val wallet: TestWallet,
private val extfvk: String,
private val extpub: String,
private val birthday: Int,
) {
val networkName = wallet.networkName
val name = "$networkName wallet"
@Test
fun testNotPlaintext() {
val message =
"is using plaintext. This will cause problems for the test. Ensure that the `lightwalletd_allow_very_insecure_connections` resource value is false"
assertFalse("$name $message", wallet.service.connectionInfo.usePlaintext)
}
@Test
fun testFilePaths() {
assertEquals(
"$name has invalid DataDB file",
"/data/user/0/cash.z.ecc.android.sdk.test/databases/TestWallet_${networkName}_Data.db",
wallet.initializer.rustBackend.pathDataDb
)
assertEquals(
"$name has invalid CacheDB file",
"/data/user/0/cash.z.ecc.android.sdk.test/databases/TestWallet_${networkName}_Cache.db",
wallet.initializer.rustBackend.pathCacheDb
)
assertEquals(
"$name has invalid CacheDB params dir",
"/data/user/0/cash.z.ecc.android.sdk.test/cache/params",
wallet.initializer.rustBackend.pathParamsDir
)
}
@Test
fun testBirthday() {
assertEquals(
"$name has invalid birthday height",
birthday,
wallet.initializer.birthday.height
)
}
@Test
fun testViewingKeys() {
assertEquals(
"$name has invalid extfvk",
extfvk,
wallet.initializer.viewingKeys[0].extfvk
)
assertEquals(
"$name has invalid extpub",
extpub,
wallet.initializer.viewingKeys[0].extpub
)
}
@Test
fun testServerConnection() {
assertEquals(
"$name has an invalid server connection",
"$networkName.lightwalletd.com:9067?usePlaintext=false",
wallet.connectionInfo
)
}
@Test
fun testLatestHeight() = runBlocking {
if (wallet.networkName == "mainnet") {
val expectedHeight = BlockExplorer.fetchLatestHeight()
// fetch height directly because the synchronizer hasn't started, yet
val downloaderHeight = wallet.service.getLatestBlockHeight()
val info = wallet.connectionInfo
assertTrue(
"$info\n ${wallet.networkName} Lightwalletd is too far behind. Downloader height $downloaderHeight is more than 10 blocks behind block explorer height $expectedHeight",
expectedHeight - 10 < downloaderHeight
)
}
}
@Test
fun testSingleBlockDownload() = runBlocking {
// fetch block directly because the synchronizer hasn't started, yet
val height = 1_000_000
val block = wallet.service.getBlockRange(height..height)[0]
assertTrue("$networkName failed to return a proper block. Height was ${block.height} but we expected $height", block.height.toInt() == height)
}
companion object {
@JvmStatic
@Parameterized.Parameters
fun wallets() = listOf(
// Testnet wallet
arrayOf(
TestWallet(TestWallet.Backups.SAMPLE_WALLET),
"zxviewtestsapling1qv0ue89kqqqqpqqyt4cl5wvssx4wqq30e5m948p07dnwl9x3u75vvnzvjwwpjkrf8yk2gva0kkxk9p8suj4xawlzw9pajuxgap83wykvsuyzfrm33a2p2m4jz2205kgzx0l2lj2kyegtnuph6crkyvyjqmfxut84nu00wxgrstu5fy3eu49nzl8jzr4chmql4ysgg2t8htn9dtvxy8c7wx9rvcerqsjqm6lqln9syk3g8rr3xpy3l4nj0kawenzpcdtnv9qmy98vdhqzaf063",
"0234965f30c8611253d035f44e68d4e2ce82150e8665c95f41ccbaf916b16c69d8",
1320000
),
// Mainnet wallet
arrayOf(
TestWallet(TestWallet.Backups.SAMPLE_WALLET, ZcashNetwork.Mainnet),
"zxviews1q0hxkupsqqqqpqzsffgrk2smjuccedua7zswf5e3rgtv3ga9nhvhjug670egshd6me53r5n083s2m9mf4va4z7t39ltd3wr7hawnjcw09eu85q0ammsg0tsgx24p4ma0uvr4p8ltx5laum2slh2whc23ctwlnxme9w4dw92kalwk5u4wyem8dynknvvqvs68ktvm8qh7nx9zg22xfc77acv8hk3qqll9k3x4v2fa26puu2939ea7hy4hh60ywma69xtqhcy4037ne8g2sg8sq",
"031c6355641237643317e2d338f5e8734c57e8aa8ce960ee22283cf2d76bef73be",
1195000
)
)
}
}

View File

@ -0,0 +1,56 @@
package cash.z.ecc.android.sdk.integration
import androidx.test.filters.MediumTest
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.util.TestWallet
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Test
/**
* This test is intended to run to make sure that basic things are functional and pinpoint what is
* not working. It was originally developed after a major refactor to find what broke.
*/
@MaintainedTest(TestPurpose.COMMIT)
@MediumTest
class SmokeTest {
@Test
fun testNotPlaintext() {
val service =
wallet.synchronizer.processor.downloader.lightWalletService as LightWalletGrpcService
Assert.assertFalse(
"Wallet is using plaintext. This will cause problems for the test. Ensure that the `lightwalletd_allow_very_insecure_connections` resource value is false",
service.connectionInfo.usePlaintext
)
}
@Test
fun testFilePaths() {
Assert.assertEquals("Invalid DataDB file", "/data/user/0/cash.z.ecc.android.sdk.test/databases/TestWallet_testnet_Data.db", wallet.initializer.rustBackend.pathDataDb)
Assert.assertEquals("Invalid CacheDB file", "/data/user/0/cash.z.ecc.android.sdk.test/databases/TestWallet_testnet_Cache.db", wallet.initializer.rustBackend.pathCacheDb)
Assert.assertEquals("Invalid CacheDB params dir", "/data/user/0/cash.z.ecc.android.sdk.test/cache/params", wallet.initializer.rustBackend.pathParamsDir)
}
@Test
fun testBirthday() {
Assert.assertEquals("Invalid birthday height", 1_320_000, wallet.initializer.birthday.height)
}
@Test
fun testViewingKeys() {
Assert.assertEquals("Invalid extfvk", "zxviewtestsapling1qv0ue89kqqqqpqqyt4cl5wvssx4wqq30e5m948p07dnwl9x3u75vvnzvjwwpjkrf8yk2gva0kkxk9p8suj4xawlzw9pajuxgap83wykvsuyzfrm33a2p2m4jz2205kgzx0l2lj2kyegtnuph6crkyvyjqmfxut84nu00wxgrstu5fy3eu49nzl8jzr4chmql4ysgg2t8htn9dtvxy8c7wx9rvcerqsjqm6lqln9syk3g8rr3xpy3l4nj0kawenzpcdtnv9qmy98vdhqzaf063", wallet.initializer.viewingKeys[0].extfvk)
Assert.assertEquals("Invalid extpub", "0234965f30c8611253d035f44e68d4e2ce82150e8665c95f41ccbaf916b16c69d8", wallet.initializer.viewingKeys[0].extpub)
}
@Test
fun testSync() = runBlocking<Unit> {
wallet.sync(120_000L)
}
companion object {
val wallet = TestWallet(TestWallet.Backups.SAMPLE_WALLET)
}
}

View File

@ -1,12 +1,20 @@
package cash.z.ecc.android.sdk.integration
package cash.z.wallet.sdk.integration
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.Synchronizer.Status.SYNCED
import cash.z.ecc.android.sdk.db.entity.isSubmitSuccess
import cash.z.ecc.android.sdk.jni.RustBackend
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.onFirst
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.tool.WalletBirthdayTool
import cash.z.ecc.android.sdk.type.ZcashNetwork
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
@ -22,22 +30,22 @@ import java.util.concurrent.CountDownLatch
class TestnetIntegrationTest : ScopedTest() {
var stopWatch = CountDownLatch(1)
val saplingActivation = synchronizer.network.saplingActivationHeight
@Test
fun testLatestBlockTest() {
val service = LightWalletGrpcService(
context,
host,
port
)
val height = service.getLatestBlockHeight()
assertTrue(height > ZcashSdk.SAPLING_ACTIVATION_HEIGHT)
assertTrue(height > saplingActivation)
}
@Test
fun testLoadBirthday() {
val (height, hash, time, tree) = Initializer.DefaultBirthdayStore.loadBirthdayFromAssets(context, ZcashSdk.SAPLING_ACTIVATION_HEIGHT + 1)
assertEquals(ZcashSdk.SAPLING_ACTIVATION_HEIGHT, height)
val (height, hash, time, tree) = WalletBirthdayTool.loadNearest(context, synchronizer.network, saplingActivation + 1)
assertEquals(saplingActivation, height)
}
@Test
@ -74,7 +82,7 @@ class TestnetIntegrationTest : ScopedTest() {
}
private suspend fun sendFunds(): Boolean {
val spendingKey = RustBackend().deriveSpendingKeys(seed)[0]
val spendingKey = DerivationTool.deriveSpendingKeys(seed, synchronizer.network)[0]
log("sending to address")
synchronizer.sendToAddress(
spendingKey,
@ -96,7 +104,6 @@ class TestnetIntegrationTest : ScopedTest() {
init { Twig.plant(TroubleshootingTwig()) }
const val host = "lightwalletd.testnet.z.cash"
const val port = 9067
private const val birthdayHeight = 963150
private const val targetHeight = 663250
private const val seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
@ -105,13 +112,15 @@ class TestnetIntegrationTest : ScopedTest() {
val toAddress = "zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0"
private val context = InstrumentationRegistry.getInstrumentation().context
private val initializer = Initializer(context, host, port, "TestnetIntegrationTests")
private val initializer = Initializer(context) { config ->
config.setNetwork(ZcashNetwork.Testnet, host)
config.importWallet(seed, birthdayHeight, ZcashNetwork.Testnet)
}
private lateinit var synchronizer: Synchronizer
@JvmStatic
@BeforeClass
fun startUp() {
initializer.importPhrase(seedPhrase, birthdayHeight, "TestnetIntegrationTests", false)
synchronizer = Synchronizer(initializer)
synchronizer.start(classScope)
}

View File

@ -1,4 +1,4 @@
// package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside // package cash.z.ecc.android.sdk.integration
//
// import cash.z.ecc.android.sdk.ext.ScopedTest
// import cash.z.ecc.android.sdk.ext.twigTask

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside
// import cash.z.ecc.android.sdk.SdkSynchronizer
// import cash.z.ecc.android.sdk.db.entity.isSubmitSuccess

View File

@ -1,4 +1,4 @@
// package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside // package cash.z.ecc.android.sdk.integration
//
// import cash.z.ecc.android.sdk.ext.ScopedTest
// import cash.z.ecc.android.sdk.ext.twig

View File

@ -1,4 +1,4 @@
// package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside // package cash.z.ecc.android.sdk.integration
//
// import cash.z.ecc.android.sdk.ext.ScopedTest
// import cash.z.ecc.android.sdk.util.DarksideTestCoordinator

View File

@ -0,0 +1,24 @@
package cash.z.ecc.android.sdk.integration.darkside
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose.DARKSIDE
import cash.z.ecc.android.sdk.annotation.TestPurpose.REGRESSION
import cash.z.ecc.android.sdk.ext.DarksideTest
import org.junit.Before
import org.junit.Test
/**
* Integration test to run in order to catch any regressions in transparent behavior.
*/
@MaintainedTest(DARKSIDE, REGRESSION)
class TransparentIntegrationTest : DarksideTest() {
@Before
fun setup() = runOnce {
sithLord.await()
}
@Test
fun sanityTest() {
validator.validateTxCount(5)
}
}

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.integration.reorgs
package cash.z.ecc.android.sdk.integration.darkside.reorgs
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.twig

View File

@ -1,4 +1,4 @@
// package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside.reorgs // package cash.z.ecc.android.sdk.integration
//
// import cash.z.ecc.android.sdk.ext.ScopedTest
// import cash.z.ecc.android.sdk.util.DarksideTestCoordinator

View File

@ -1,4 +1,4 @@
// package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside.reorgs // package cash.z.ecc.android.sdk.integration
//
// import androidx.test.platform.app.InstrumentationRegistry
// import cash.z.ecc.android.sdk.Initializer

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside.reorgs
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.util.DarksideTestCoordinator

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.integration
package cash.z.ecc.android.sdk.integration.darkside.reorgs
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.twig

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.integration.reorgs
package cash.z.ecc.android.sdk.integration.darkside.reorgs
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.toHex

View File

@ -0,0 +1,29 @@
package cash.z.ecc.android.sdk.integration.darkside.reproduce
import cash.z.ecc.android.sdk.ext.DarksideTest
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
class ReproduceZ2TFailureTest : DarksideTest() {
@Before
fun setup() {
println("dBUG RUNNING")
}
@Test
fun once() {
}
@Test
fun twice() {
}
companion object {
@JvmStatic
@BeforeClass
fun beforeAll() {
println("dBUG BEFOERE IOT ALL")
}
}
}

View File

@ -1,15 +1,18 @@
package cash.z.ecc.android.sdk.integration.service
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose
import cash.z.ecc.android.sdk.block.CompactBlockDownloader
import cash.z.ecc.android.sdk.block.CompactBlockStore
import cash.z.ecc.android.sdk.exception.LightWalletException.ChangeServerException.ChainInfoNotMatching
import cash.z.ecc.android.sdk.exception.LightWalletException.ChangeServerException.StatusException
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.service.LightWalletService
import cash.z.ecc.android.sdk.type.ZcashNetwork
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@ -24,15 +27,19 @@ import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.Spy
@MaintainedTest(TestPurpose.REGRESSION)
@RunWith(AndroidJUnit4::class)
@SmallTest
class ChangeServiceTest : ScopedTest() {
val network = ZcashNetwork.Mainnet
@Mock
lateinit var mockBlockStore: CompactBlockStore
var mockCloseable: AutoCloseable? = null
@Spy
val service = LightWalletGrpcService(context, ZcashSdk.DEFAULT_LIGHTWALLETD_HOST)
val service = LightWalletGrpcService(context, network)
lateinit var downloader: CompactBlockDownloader
lateinit var otherService: LightWalletService
@ -41,7 +48,7 @@ class ChangeServiceTest : ScopedTest() {
fun setup() {
initMocks()
downloader = CompactBlockDownloader(service, mockBlockStore)
otherService = LightWalletGrpcService(context, "lightwalletd.electriccoin.co", 9067)
otherService = LightWalletGrpcService(context, "lightwalletd.electriccoin.co")
}
@After
@ -56,7 +63,7 @@ class ChangeServiceTest : ScopedTest() {
@Test
fun testSanityCheck() {
val result = service.getLatestBlockHeight()
assertTrue(result > ZcashSdk.SAPLING_ACTIVATION_HEIGHT)
assertTrue(result > network.saplingActivationHeight)
}
@Test
@ -66,16 +73,20 @@ class ChangeServiceTest : ScopedTest() {
assertEquals(1_001, result)
}
/**
* Repeatedly connect to servers and download a range of blocks. Switch part way through and
* verify that the servers change over, even while actively downloading.
*/
@Test
fun testSwitchWhileActive() = runBlocking {
val start = 900_000
val count = 5
val vendors = mutableListOf<String>()
var oldVendor = downloader.getServerInfo().vendor
val differentiators = mutableListOf<String>()
var initialValue = downloader.getServerInfo().buildUser
val job = testScope.launch {
repeat(count) {
vendors.add(downloader.getServerInfo().vendor)
twig("downloading from ${vendors.last()}")
differentiators.add(downloader.getServerInfo().buildUser)
twig("downloading from ${differentiators.last()}")
downloader.downloadBlockRange(start..(start + 100 * it))
delay(10L)
}
@ -85,8 +96,8 @@ class ChangeServiceTest : ScopedTest() {
downloader.changeService(otherService)
}
job.join()
assertTrue(vendors.count { it == oldVendor } < vendors.size)
assertEquals(count, vendors.size)
assertTrue(differentiators.count { it == initialValue } < differentiators.size)
assertEquals(count, differentiators.size)
}
@Test
@ -105,7 +116,7 @@ class ChangeServiceTest : ScopedTest() {
@Test
fun testSwitchToTestnetFails() = runBlocking {
var caughtException: Throwable? = null
downloader.changeService(LightWalletGrpcService(context, "lightwalletd.testnet.electriccoin.co", 9067)) {
downloader.changeService(LightWalletGrpcService(context, ZcashNetwork.Testnet)) {
caughtException = it
}
assertNotNull("Using an invalid host should generate an exception.", caughtException)
@ -114,7 +125,7 @@ class ChangeServiceTest : ScopedTest() {
caughtException is ChainInfoNotMatching
)
(caughtException as ChainInfoNotMatching).propertyNames.let { props ->
arrayOf("consensusBranchId", "saplingActivationHeight", "chainName").forEach {
arrayOf("saplingActivationHeight", "chainName").forEach {
assertTrue(
"$it should be a non-matching property but properties were [$props]", props.contains(it, true)
)

View File

@ -1,59 +1,82 @@
package cash.z.ecc.android.sdk.jni
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode
import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.ZcashNetwork
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
@MaintainedTest(TestPurpose.REGRESSION)
@RunWith(AndroidJUnit4::class)
@SmallTest
class TransparentTest {
lateinit var expected: Expected
lateinit var network: ZcashNetwork
@Before
fun setup() {
// TODO: parameterize this for both networks
// if (BuildConfig.FLAVOR == "zcashtestnet") {
expected = ExpectedTestnet
network = ZcashNetwork.Testnet
// } else {
// expected = ExpectedMainnet
// network = ZcashNetwork.Mainnet
// }
}
@Test
fun deriveTransparentSecretKeyTest() {
assertEquals(Expected.tskCompressed, DerivationTool.deriveTransparentSecretKey(SEED))
assertEquals(expected.tskCompressed, DerivationTool.deriveTransparentSecretKey(SEED, network = network))
}
@Test
fun deriveTransparentAddressTest() {
assertEquals(Expected.tAddr, DerivationTool.deriveTransparentAddress(SEED))
assertEquals(expected.tAddr, DerivationTool.deriveTransparentAddress(SEED, network = network))
}
@Test
fun deriveTransparentAddressFromSecretKeyTest() {
assertEquals(Expected.tAddr, DerivationTool.deriveTransparentAddress(Expected.tskCompressed))
assertEquals(expected.tAddr, DerivationTool.deriveTransparentAddressFromPrivateKey(expected.tskCompressed, network = network))
}
// @Test
// fun deriveTransparentAddressFromSecretKeyTest2() {
// while(false) {
// MnemonicCode(COUNT_24).let { phrase ->
// val addr = DerivationTool.deriveShieldedAddress(phrase.toSeed())
// twig("$addr${String(phrase.chars)}\t")
// }
// }
// }
@Test
fun deriveUnifiedViewingKeysFromSeedTest() {
val uvks = DerivationTool.deriveUnifiedViewingKeys(SEED, network = network)
assertEquals(1, uvks.size)
val uvk = uvks.first()
assertEquals(expected.zAddr, DerivationTool.deriveShieldedAddress(uvk.extfvk, network = network))
assertEquals(expected.tAddr, DerivationTool.deriveTransparentAddressFromPublicKey(uvk.extpub, network = network))
}
companion object {
const val PHRASE = "deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"
val MNEMONIC = MnemonicCode(PHRASE)
val SEED = MNEMONIC.toSeed()
object Expected {
val tAddr = "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4"
object ExpectedMainnet : Expected {
override val tAddr = "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4"
override val zAddr = "zs1yc4sgtfwwzz6xfsy2xsradzr6m4aypgxhfw2vcn3hatrh5ryqsr08sgpemlg39vdh9kfupx20py"
override val tskCompressed = "L4BvDC33yLjMRxipZvdiUmdYeRfZmR8viziwsVwe72zJdGbiJPv2"
override val tpk = "03b1d7fb28d17c125b504d06b1530097e0a3c76ada184237e3bc0925041230a5af"
}
// private key in compressed Wallet Import Format (WIF)
val tskCompressed = "L4BvDC33yLjMRxipZvdiUmdYeRfZmR8viziwsVwe72zJdGbiJPv2"
object ExpectedTestnet : Expected {
override val tAddr = "tm9v3KTsjXK8XWSqiwFjic6Vda6eHY9Mjjq"
override val zAddr = "ztestsapling1wn3tw9w5rs55x5yl586gtk72e8hcfdq8zsnjzcu8p7ghm8lrx54axc74mvm335q7lmy3g0sqje6"
override val tskCompressed = "KzVugoXxR7AtTMdR5sdJtHxCNvMzQ4H196k7ATv4nnjoummsRC9G"
override val tpk = "03b1d7fb28d17c125b504d06b1530097e0a3c76ada184237e3bc0925041230a5af"
}
@BeforeClass
@ -62,4 +85,11 @@ class TransparentTest {
Twig.plant(TroubleshootingTwig(formatter = { "@TWIG $it" }))
}
}
interface Expected {
val tAddr: String
val zAddr: String
val tskCompressed: String
val tpk: String
}
}

View File

@ -10,6 +10,7 @@ import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.ZcashNetwork.Testnet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.catch
@ -28,9 +29,6 @@ class ShieldFundsSample {
val SEED_PHRASE = "wish puppy smile loan doll curve hole maze file ginger hair nose key relax knife witness cannon grab despair throw review deal slush frame" // \"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread\"//\"deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"//"deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"
// simple flag to turn off actually spending funds
val IS_DRY_RUN = true
/**
* This test will construct a t2z transaction. It is safe to run this repeatedly, because
* nothing is submitted to the network (because the keys don't match the address so the encoding
@ -51,22 +49,25 @@ class ShieldFundsSample {
// when startHeight is null, it will use the latest checkpoint
class SimpleWallet(seedPhrase: String, startHeight: Int? = null) {
// simple flag to turn off actually spending funds
val IS_DRY_RUN = true
val walletScope = CoroutineScope(
SupervisorJob() + newFixedThreadPoolContext(3, this.javaClass.simpleName)
)
private val context = InstrumentationRegistry.getInstrumentation().context
private val seed: ByteArray = Mnemonics.MnemonicCode(seedPhrase).toSeed()
private val shieldedSpendingKey = DerivationTool.deriveSpendingKeys(seed)[0]
private val transparentSecretKey = DerivationTool.deriveTransparentSecretKey(seed)
private val shieldedAddress = DerivationTool.deriveShieldedAddress(seed)
private val shieldedSpendingKey = DerivationTool.deriveSpendingKeys(seed, Testnet)[0]
private val transparentSecretKey = DerivationTool.deriveTransparentSecretKey(seed, Testnet)
private val shieldedAddress = DerivationTool.deriveShieldedAddress(seed, Testnet)
// t1b9Y6PESSGavavgge3ruTtX9X83817V29s
private val transparentAddress = DerivationTool.deriveTransparentAddress(seed)
private val transparentAddress = DerivationTool.deriveTransparentAddress(seed, Testnet)
private val host = "lightwalletd.testnet.electriccoin.co"
private val config = Initializer.Config {
it.setSeed(seed)
it.setSeed(seed, Testnet)
it.setBirthdayHeight(startHeight, false)
it.server("lightwalletd.electriccoin.co", 9067)
it.setNetwork(Testnet, host)
}
val synchronizer = Synchronizer(Initializer(context, config))

View File

@ -0,0 +1,229 @@
package cash.z.ecc.android.sdk.sample
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.type.ZcashNetwork.Testnet
import cash.z.ecc.android.sdk.util.TestWallet
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Test
/**
* Sample tests are used to demonstrate functionality. This one attempts to setup a scenario where
* one wallet shields funds and the other restores from the blockchain. Ultimately, they should have
* the same data.
*/
class TransparentRestoreSample {
val TX_VALUE = ZcashSdk.MINERS_FEE_ZATOSHI / 2
// val walletA = SimpleWallet(SEED_PHRASE, "WalletA")
// the wallet that only restores what everyone else did
// val walletB = SimpleWallet(SEED_PHRASE, "WalletB")
// // the wallet that sends Z2T transactions
//
// // sandbox wallet
// val walletSandbox = SimpleWallet(SEED_PHRASE, "WalletC")
// val walletZ2T = SimpleWallet(SEED_PHRASE, "WalletZ2T")
// val externalTransparentAddress =
// DerivationTool.deriveTransparentAddress(Mnemonics.MnemonicCode(RANDOM_PHRASE).toSeed(), Testnet)
// @Test
fun sendZ2Texternal() = runBlocking {
twig("Syncing WalletExt")
val extWallet = TestWallet(TestWallet.Backups.ALICE, alias = "WalletE")
extWallet.sync()
// extWallet.send(542, walletSandbox.transparentAddress, "External funds memo is lost, though")
delay(1000)
twig("Done sending funds to external address (Z->T COMPLETE!)")
}
// @Test
fun sendZ2T() = runBlocking {
// walletSandbox.sync()
// walletZ2T.send(543, externalTransparentAddress, "External funds memo is lost, though")
delay(1000)
twig("Done sending funds to external address (Z->T COMPLETE!)")
}
// @Test
fun autoShield() = runBlocking<Unit> {
val wallet = TestWallet(TestWallet.Backups.SAMPLE_WALLET, alias = "WalletC")
wallet.sync()
twig("Done syncing wallet!")
val tbalance = wallet.transparentBalance()
val address = wallet.transparentAddress
twig("t-avail: ${tbalance.availableZatoshi} t-total: ${tbalance.totalZatoshi}")
Assert.assertTrue("Not enough funds to run sample. Expected some Zatoshi but found ${tbalance.availableZatoshi}. Try adding funds to $address", tbalance.availableZatoshi > 0)
twig("Shielding available transparent funds!")
// wallet.shieldFunds()
}
// @Test
fun cli() = runBlocking<Unit> {
// val wallet = SimpleWallet(SEED_PHRASE, "WalletCli")
// wallet.sync()
// wallet.rewindToHeight(1343500).join(45_000)
val wallet = TestWallet(TestWallet.Backups.SAMPLE_WALLET, alias = "WalletC")
// wallet.sync().rewindToHeight(1339178).join(10000)
wallet.sync().rewindToHeight(1339178).send(
"ztestsapling17zazsl8rryl8kjaqxnr2r29rw9d9a2mud37ugapm0s8gmyv0ue43h9lqwmhdsp3nu9dazeqfs6l",
"is send broken?"
).join(5)
}
@Test
fun kris() = runBlocking<Unit> {
val wallet0 = TestWallet(TestWallet.Backups.SAMPLE_WALLET.seedPhrase, "tmpabc", Testnet, startHeight = 1330190)
// val wallet1 = SimpleWallet(WALLET0_PHRASE, "Wallet1")
wallet0.sync() // .shieldFunds()
// .send(amount = 1543L, memo = "")
.join()
// wallet1.sync().join(5_000L)
}
/*
*/
/**
* Sanity check that the wallet has enough funds for the test
*/
// @Test
fun hasFunds() = runBlocking<Unit> {
val walletSandbox = TestWallet(TestWallet.Backups.SAMPLE_WALLET.seedPhrase, "WalletC", Testnet, startHeight = 1330190)
// val job = walletA.walletScope.launch {
// twig("Syncing WalletA")
// walletA.sync()
// }
twig("Syncing WalletSandbox")
walletSandbox.sync()
// job.join()
delay(500)
twig("Done syncing both wallets!")
// val value = walletA.available
// val address = walletA.shieldedAddress
// Assert.assertTrue("Not enough funds to run sample. Expected at least $TX_VALUE Zatoshi but found $value. Try adding funds to $address", value >= TX_VALUE)
// send z->t
// walletA.send(TX_VALUE, walletA.transparentAddress, "${TransparentRestoreSample::class.java.simpleName} z->t")
walletSandbox.rewindToHeight(1339178)
twig("Done REWINDING!")
twig("T-ADDR (for the win!): ${walletSandbox.transparentAddress}")
delay(500)
// walletB.sync()
// rewind database B to height then rescan
}
// // when startHeight is null, it will use the latest checkpoint
// class SimpleWallet(
// seedPhrase: String,
// alias: String = ZcashSdk.DEFAULT_ALIAS,
// startHeight: Int? = null
// ) {
// val walletScope = CoroutineScope(
// SupervisorJob() + newFixedThreadPoolContext(3, this.javaClass.simpleName)
// )
// private val context = InstrumentationRegistry.getInstrumentation().context
// private val seed: ByteArray = Mnemonics.MnemonicCode(seedPhrase).toSeed()
// private val shieldedSpendingKey = DerivationTool.deriveSpendingKeys(seed, Testnet)[0]
// private val transparentSecretKey = DerivationTool.deriveTransparentSecretKey(seed, Testnet)
// private val host = "lightwalletd.testnet.electriccoin.co"
// private val initializer = Initializer(context) { config ->
// config.importWallet(seed, startHeight)
// config.setNetwork(Testnet, host)
// config.alias = alias
// }
//
// val synchronizer = Synchronizer(initializer)
// val available get() = synchronizer.latestBalance.availableZatoshi
// val shieldedAddress = DerivationTool.deriveShieldedAddress(seed, Testnet)
// val transparentAddress = DerivationTool.deriveTransparentAddress(seed, Testnet)
// val birthdayHeight get() = synchronizer.latestBirthdayHeight
//
// suspend fun transparentBalance(): WalletBalance {
// synchronizer.refreshUtxos(transparentAddress, synchronizer.latestBirthdayHeight)
// return synchronizer.getTransparentBalance(transparentAddress)
// }
//
// suspend fun sync(): SimpleWallet {
// if (!synchronizer.isStarted) {
// twig("Starting sync")
// synchronizer.start(walletScope)
// } else {
// twig("Awaiting next SYNCED status")
// }
//
// // block until synced
// synchronizer.status.first { it == SYNCED }
// twig("Synced!")
// return this
// }
//
// suspend fun send(address: String = transparentAddress, memo: String = "", amount: Long = 500L): SimpleWallet {
// synchronizer.sendToAddress(shieldedSpendingKey, amount, address, memo)
// .takeWhile { it.isPending() }
// .collect {
// twig("Updated transaction: $it")
// }
// return this
// }
//
// suspend fun rewindToHeight(height: Int): SimpleWallet {
// synchronizer.rewindToHeight(height, false)
// return this
// }
//
// suspend fun shieldFunds(): SimpleWallet {
// twig("checking $transparentAddress for transactions!")
// synchronizer.refreshUtxos(transparentAddress, 935000).let { count ->
// twig("FOUND $count new UTXOs")
// }
//
// synchronizer.getTransparentBalance(transparentAddress).let { walletBalance ->
// twig("FOUND utxo balance of total: ${walletBalance.totalZatoshi} available: ${walletBalance.availableZatoshi}")
//
// if (walletBalance.availableZatoshi > 0L) {
// synchronizer.shieldFunds(shieldedSpendingKey, transparentSecretKey)
// .onCompletion { twig("done shielding funds") }
// .catch { twig("Failed with $it") }
// .collect()
// }
// }
//
// return this
// }
//
// suspend fun join(timeout: Long? = null): SimpleWallet {
// // block until stopped
// twig("Staying alive until synchronizer is stopped!")
// if (timeout != null) {
// twig("Scheduling a stop in ${timeout}ms")
// walletScope.launch {
// delay(timeout)
// synchronizer.stop()
// }
// }
// synchronizer.status.first { it == Synchronizer.Status.STOPPED }
// twig("Stopped!")
// return this
// }
//
// companion object {
// init {
// Twig.plant(TroubleshootingTwig())
// }
// }
// }
}

View File

@ -1,6 +1,9 @@
package cash.z.ecc.android.sdk.transaction
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.annotation.MaintainedTest
import cash.z.ecc.android.sdk.annotation.TestPurpose
import cash.z.ecc.android.sdk.db.entity.EncodedTransaction
import cash.z.ecc.android.sdk.db.entity.PendingTransaction
import cash.z.ecc.android.sdk.db.entity.isCancelled
@ -29,7 +32,9 @@ import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@MaintainedTest(TestPurpose.REGRESSION)
@RunWith(AndroidJUnit4::class)
@SmallTest
class PersistentTransactionManagerTest : ScopedTest() {
@Mock lateinit var mockEncoder: TransactionEncoder

View File

@ -2,6 +2,7 @@ package cash.z.ecc.android.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.ZcashNetwork
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
@ -35,7 +36,7 @@ class AddressGeneratorUtil {
.map { seedPhrase ->
mnemonics.toSeed(seedPhrase.toCharArray())
}.map { seed ->
DerivationTool.deriveShieldedAddress(seed)
DerivationTool.deriveShieldedAddress(seed, ZcashNetwork.Mainnet)
}.collect { address ->
println("xrxrx2\t$address")
assertTrue(address.startsWith("zs1"))

View File

@ -7,6 +7,8 @@ import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.tool.WalletBirthdayTool
import cash.z.ecc.android.sdk.type.WalletBirthday
import cash.z.ecc.android.sdk.type.ZcashNetwork
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
@ -25,8 +27,7 @@ import java.io.IOException
@ExperimentalCoroutinesApi
class BalancePrinterUtil {
private val host = "lightd-main.zecwallet.co"
private val port = 443
private val network = ZcashNetwork.Mainnet
private val downloadBatchSize = 9_000
private val birthdayHeight = 523240
@ -44,14 +45,14 @@ class BalancePrinterUtil {
// private val rustBackend = RustBackend.init(context, cacheDbName, dataDbName)
private lateinit var birthday: WalletBirthdayTool.WalletBirthday
private lateinit var birthday: WalletBirthday
private var synchronizer: Synchronizer? = null
@Before
fun setup() {
Twig.plant(TroubleshootingTwig())
cacheBlocks()
birthday = WalletBirthdayTool.loadNearest(context, birthdayHeight)
birthday = WalletBirthdayTool.loadNearest(context, network, birthdayHeight)
}
private fun cacheBlocks() = runBlocking {
@ -78,8 +79,8 @@ class BalancePrinterUtil {
}.collect { seed ->
// TODO: clear the dataDb but leave the cacheDb
val initializer = Initializer(context) { config ->
config.importWallet(seed, birthdayHeight)
config.server(host, port)
config.importWallet(seed, birthdayHeight, network)
config.setNetwork(network)
config.alias = alias
}
/*

View File

@ -2,9 +2,9 @@ package cash.z.ecc.android.sdk.util
import android.content.Context
import cash.z.ecc.android.sdk.R
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.type.ZcashNetwork
import cash.z.wallet.sdk.rpc.Darkside
import cash.z.wallet.sdk.rpc.Darkside.DarksideTransactionsURL
import cash.z.wallet.sdk.rpc.DarksideStreamerGrpc
@ -23,7 +23,7 @@ class DarksideApi(
constructor(
appContext: Context,
host: String,
port: Int = ZcashSdk.DEFAULT_LIGHTWALLETD_PORT,
port: Int = ZcashNetwork.Mainnet.defaultPort,
usePlainText: Boolean = appContext.resources.getBoolean(
R.bool.lightwalletd_allow_very_insecure_connections
)
@ -42,8 +42,8 @@ class DarksideApi(
fun reset(
saplingActivationHeight: Int = 419200,
branchId: String = "2bb40e60", // Blossom,
chainName: String = "darkside"
branchId: String = "e9ff75a6", // Canopy,
chainName: String = "darkside${ZcashNetwork.Mainnet.networkName}"
) = apply {
twig("resetting darksidewalletd with saplingActivation=$saplingActivationHeight branchId=$branchId chainName=$chainName")
Darkside.DarksideMetaState.newBuilder()

View File

@ -1,32 +1,35 @@
package cash.z.ecc.android.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.SdkSynchronizer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ScopedTest
import cash.z.ecc.android.sdk.ext.seedPhrase
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.ZcashNetwork
import io.grpc.StatusRuntimeException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: String = "DarksideTestCoordinator") {
private val port = 9067
private val birthdayHeight = 663150
class DarksideTestCoordinator(val wallet: TestWallet) {
constructor(
alias: String = "DarksideTestCoordinator",
seedPhrase: String = DEFAULT_SEED_PHRASE,
startHeight: Int = DEFAULT_START_HEIGHT,
host: String = "127.0.0.1",
network: ZcashNetwork = ZcashNetwork.Mainnet,
port: Int = network.defaultPort,
) : this(TestWallet(seedPhrase, alias, network, host, port, startHeight))
private val targetHeight = 663250
private val seedPhrase =
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
private val context = InstrumentationRegistry.getInstrumentation().context
// dependencies: private
@ -35,11 +38,10 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
// dependencies: public
val validator = DarksideTestValidator()
val chainMaker = DarksideChainMaker()
// var initializer = Initializer(context, Initializer.Builder(host, port, testName))
lateinit var synchronizer: SdkSynchronizer
val spendingKey: String get() = DerivationTool.deriveSpendingKeys(SimpleMnemonics().toSeed(seedPhrase.toCharArray()))[0]
// wallet delegates
val synchronizer get() = wallet.synchronizer
val send get() = wallet::send
//
// High-level APIs
//
@ -74,14 +76,9 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
*/
fun initiate() {
twig("*************** INITIALIZING TEST COORDINATOR (ONLY ONCE) ***********************")
val initializer = Initializer(context) { config ->
config.seedPhrase(seedPhrase)
config.setBirthdayHeight(birthdayHeight)
config.alias = testName
}
synchronizer = Synchronizer(initializer) as SdkSynchronizer
val channel = (synchronizer as SdkSynchronizer).channel
val channel = synchronizer.channel
darkside = DarksideApi(channel)
darkside.reset()
}
// fun triggerSmallReorg() {
@ -96,6 +93,7 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
synchronizer.start(scope)
}
// redo this as a call to wallet but add delay time to wallet join() function
/**
* Waits for, at most, the given amount of time for the synchronizer to download and scan blocks
* and reach a 'SYNCED' status.
@ -124,27 +122,19 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
}
}
/**
* Send a transaction and wait until it has been fully created and successfully submitted, which
* takes about 10 seconds.
*/
suspend fun createAndSubmitTx(
zatoshi: Long,
toAddress: String,
memo: String = "",
fromAccountIndex: Int = 0
) = coroutineScope {
Twig.sprout("sending")
var job: Job? = null
job = synchronizer
.sendToAddress(spendingKey, zatoshi, toAddress, memo, fromAccountIndex)
.onEach {
twig("got an update submitted yet? ${it.isSubmitSuccess()}")
if (it.isSubmitSuccess()) job?.cancel()
}.launchIn(this)
job.join()
Twig.clip("sending")
}
// /**
// * Send a transaction and wait until it has been fully created and successfully submitted, which
// * takes about 10 seconds.
// */
// suspend fun createAndSubmitTx(
// zatoshi: Long,
// toAddress: String,
// memo: String = "",
// fromAccountIndex: Int = 0
// ) = coroutineScope {
//
// wallet.send(toAddress, memo, zatoshi, fromAccountIndex)
// }
fun stall(delay: Long = 5000L) = runBlocking {
twig("*** Stalling for ${delay}ms ***")
@ -225,7 +215,7 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
}
}
suspend fun validateBalance(available: Long = -1, total: Long = -1, accountIndex: Int = 0) {
val balance = synchronizer.processor.getBalanceInfo(accountIndex)
val balance = (synchronizer as SdkSynchronizer).processor.getBalanceInfo(accountIndex)
if (available > 0) {
assertEquals("invalid available balance", available, balance.availableZatoshi)
}
@ -314,5 +304,7 @@ class DarksideTestCoordinator(val host: String = "127.0.0.1", val testName: Stri
private const val largeReorg =
"https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/after-large-reorg.txt"
private const val DEFAULT_START_HEIGHT = 663150
private const val DEFAULT_SEED_PHRASE =
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
}
}

View File

@ -0,0 +1,161 @@
package cash.z.ecc.android.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.SdkSynchronizer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.db.entity.isPending
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.WalletBalance
import cash.z.ecc.android.sdk.type.ZcashNetwork
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch
import kotlinx.coroutines.newFixedThreadPoolContext
import java.util.concurrent.TimeoutException
/**
* A simple wallet that connects to testnet for integration testing. The intention is that it is
* easy to drive and nice to use.
*/
class TestWallet(
val seedPhrase: String,
val alias: String = "TestWallet",
val network: ZcashNetwork = ZcashNetwork.Testnet,
val host: String = network.defaultHost,
startHeight: Int? = null,
val port: Int = network.defaultPort,
) {
constructor(
backup: Backups,
network: ZcashNetwork = ZcashNetwork.Testnet,
alias: String = "TestWallet"
) : this(
backup.seedPhrase,
network = network,
startHeight = backup.testnetBirthday,
alias = alias
)
val walletScope = CoroutineScope(
SupervisorJob() + newFixedThreadPoolContext(3, this.javaClass.simpleName)
)
private val context = InstrumentationRegistry.getInstrumentation().context
private val seed: ByteArray = Mnemonics.MnemonicCode(seedPhrase).toSeed()
private val shieldedSpendingKey = DerivationTool.deriveSpendingKeys(seed, network = network)[0]
private val transparentSecretKey = DerivationTool.deriveTransparentSecretKey(seed, network = network)
val initializer = Initializer(context) { config ->
config.importWallet(seed, startHeight, network, host, alias = alias)
}
val synchronizer: SdkSynchronizer = Synchronizer(initializer) as SdkSynchronizer
val service = (synchronizer.processor.downloader.lightWalletService as LightWalletGrpcService)
val available get() = synchronizer.latestBalance.availableZatoshi
val shieldedAddress = DerivationTool.deriveShieldedAddress(seed, network = network)
val transparentAddress = DerivationTool.deriveTransparentAddress(seed, network = network)
val birthdayHeight get() = synchronizer.latestBirthdayHeight
val networkName get() = synchronizer.network.networkName
val connectionInfo get() = service.connectionInfo.toString()
suspend fun transparentBalance(): WalletBalance {
synchronizer.refreshUtxos(transparentAddress, synchronizer.latestBirthdayHeight)
return synchronizer.getTransparentBalance(transparentAddress)
}
suspend fun sync(timeout: Long = -1): TestWallet {
val killSwitch = walletScope.launch {
if (timeout > 0) {
delay(timeout)
throw TimeoutException("Failed to sync wallet within ${timeout}ms")
}
}
if (!synchronizer.isStarted) {
twig("Starting sync")
synchronizer.start(walletScope)
} else {
twig("Awaiting next SYNCED status")
}
// block until synced
synchronizer.status.first { it == Synchronizer.Status.SYNCED }
killSwitch.cancel()
twig("Synced!")
return this
}
suspend fun send(address: String = transparentAddress, memo: String = "", amount: Long = 500L, fromAccountIndex: Int = 0): TestWallet {
Twig.sprout("$alias sending")
synchronizer.sendToAddress(shieldedSpendingKey, amount, address, memo, fromAccountIndex)
.takeWhile { it.isPending() }
.collect {
twig("Updated transaction: $it")
}
Twig.clip("$alias sending")
return this
}
suspend fun rewindToHeight(height: Int): TestWallet {
synchronizer.rewindToHeight(height, false)
return this
}
suspend fun shieldFunds(): TestWallet {
twig("checking $transparentAddress for transactions!")
synchronizer.refreshUtxos(transparentAddress, 935000).let { count ->
twig("FOUND $count new UTXOs")
}
synchronizer.getTransparentBalance(transparentAddress).let { walletBalance ->
twig("FOUND utxo balance of total: ${walletBalance.totalZatoshi} available: ${walletBalance.availableZatoshi}")
if (walletBalance.availableZatoshi > 0L) {
synchronizer.shieldFunds(shieldedSpendingKey, transparentSecretKey)
.onCompletion { twig("done shielding funds") }
.catch { twig("Failed with $it") }
.collect()
}
}
return this
}
suspend fun join(timeout: Long? = null): TestWallet {
// block until stopped
twig("Staying alive until synchronizer is stopped!")
if (timeout != null) {
twig("Scheduling a stop in ${timeout}ms")
walletScope.launch {
delay(timeout)
synchronizer.stop()
}
}
synchronizer.status.first { it == Synchronizer.Status.STOPPED }
twig("Stopped!")
return this
}
companion object {
init {
Twig.enabled(true)
}
}
enum class Backups(val seedPhrase: String, val testnetBirthday: Int) {
DEFAULT("column rhythm acoustic gym cost fit keen maze fence seed mail medal shrimp tell relief clip cannon foster soldier shallow refuse lunar parrot banana", 1_355_928),
SAMPLE_WALLET("input frown warm senior anxiety abuse yard prefer churn reject people glimpse govern glory crumble swallow verb laptop switch trophy inform friend permit purpose", 1_330_190),
ALICE("quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten", 1_330_190),
BOB("canvas wine sugar acquire garment spy tongue odor hole cage year habit bullet make label human unit option top calm neutral try vocal arena", 1_330_190),
;
}
}

View File

@ -3,16 +3,17 @@ package cash.z.ecc.android.sdk.util
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.type.ZcashNetwork
import org.junit.Ignore
import org.junit.Test
class TransactionCounterUtil {
private val network = ZcashNetwork.Mainnet
private val context = InstrumentationRegistry.getInstrumentation().context
private val service = LightWalletGrpcService(context, ZcashSdk.DEFAULT_LIGHTWALLETD_HOST, ZcashSdk.DEFAULT_LIGHTWALLETD_PORT)
private val service = LightWalletGrpcService(context, network)
init {
Twig.plant(TroubleshootingTwig())

View File

@ -1,7 +0,0 @@
{
"network": "main",
"height": 663150,
"hash": "0000000002fd3be4c24c437bd22620901617125ec2a3a6c902ec9a6c06f734fc",
"time": 1576821833,
"tree": "01ec6278a1bed9e1b080fd60ef50eb17411645e3746ff129283712bc4757ecc833001001b4e1d4a26ac4a2810b57a14f4ffb69395f55dde5674ecd2462af96f9126e054701a36afb68534f640938bdffd80dfcb3f4d5e232488abbf67d049b33a761e7ed6901a16e35205fb7fe626a9b13fc43e1d2b98a9c241f99f93d5e93a735454073025401f5b9bcbf3d0e3c83f95ee79299e8aeadf30af07717bda15ffb7a3d00243b58570001fa6d4c2390e205f81d86b85ace0b48f3ce0afb78eeef3e14c70bcfd7c5f0191c0000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
}

View File

@ -1,132 +0,0 @@
package cash.z.ecc.android.sdk.integration
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.Synchronizer.Status.SYNCED
import cash.z.ecc.android.sdk.db.entity.isSubmitSuccess
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.ext.onFirst
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.tool.WalletBirthdayTool
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import org.junit.AfterClass
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Test
import java.util.concurrent.CountDownLatch
class IntegrationTest {
var stopWatch = CountDownLatch(1)
@Test
fun testLatestBlockTest() {
val service = LightWalletGrpcService(
context,
host,
port
)
val height = service.getLatestBlockHeight()
assertTrue(height > ZcashSdk.SAPLING_ACTIVATION_HEIGHT)
}
@Test
fun testLoadBirthday() {
val (height, hash, time, tree) = WalletBirthdayTool.loadNearest(context, ZcashSdk.SAPLING_ACTIVATION_HEIGHT + 1)
assertEquals(ZcashSdk.SAPLING_ACTIVATION_HEIGHT, height)
}
@Test
fun getAddress() = runBlocking {
assertEquals(address, synchronizer.getAddress())
}
@Test
fun testBalance() = runBlocking {
var availableBalance: Long = 0L
synchronizer.balances.onFirst {
availableBalance = it.availableZatoshi
}
synchronizer.status.filter { it == SYNCED }.onFirst {
delay(100)
}
assertTrue(
"No funds available when we expected a balance greater than zero!",
availableBalance > 0
)
}
@Test
@Ignore
fun testSpend() = runBlocking {
var success = false
synchronizer.balances.filter { it.availableZatoshi > 0 }.onEach {
success = sendFunds()
}.first()
log("asserting $success")
assertTrue(success)
}
private suspend fun sendFunds(): Boolean {
val spendingKey = DerivationTool.deriveSpendingKeys(seed)[0]
log("sending to address")
synchronizer.sendToAddress(
spendingKey,
ZcashSdk.MINERS_FEE_ZATOSHI,
toAddress,
"first mainnet tx from the SDK"
).filter { it.isSubmitSuccess() }.onFirst {
log("DONE SENDING!!!")
}
log("returning true from sendFunds")
return true
}
fun log(message: String) {
twig("\n---\n[TESTLOG]: $message\n---\n")
}
companion object {
init { Twig.plant(TroubleshootingTwig()) }
const val host = "lightd-main.zecwallet.co"
const val port = 443
val seed = "cash.z.ecc.android.sdk.integration.IntegrationTest.seed.value.64bytes".toByteArray()
val birthdayHeight = 843_000
val address = "zs1m30y59wxut4zk9w24d6ujrdnfnl42hpy0ugvhgyhr8s0guszutqhdj05c7j472dndjstulph74m"
val toAddress = "zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0"
private val context = InstrumentationRegistry.getInstrumentation().context
private val initializer = Initializer(context) { config ->
config.setSeed(seed)
config.server(host, port)
config.setBirthdayHeight(birthdayHeight)
}
private val synchronizer: Synchronizer = Synchronizer(initializer)
@JvmStatic
@BeforeClass
fun startUp() {
synchronizer.start()
}
@JvmStatic
@AfterClass
fun tearDown() {
synchronizer.stop()
}
}
}

View File

@ -1,7 +0,0 @@
{
"network": "main",
"height": 663150,
"hash": "0000000002fd3be4c24c437bd22620901617125ec2a3a6c902ec9a6c06f734fc",
"time": 1576821833,
"tree": "01ec6278a1bed9e1b080fd60ef50eb17411645e3746ff129283712bc4757ecc833001001b4e1d4a26ac4a2810b57a14f4ffb69395f55dde5674ecd2462af96f9126e054701a36afb68534f640938bdffd80dfcb3f4d5e232488abbf67d049b33a761e7ed6901a16e35205fb7fe626a9b13fc43e1d2b98a9c241f99f93d5e93a735454073025401f5b9bcbf3d0e3c83f95ee79299e8aeadf30af07717bda15ffb7a3d00243b58570001fa6d4c2390e205f81d86b85ace0b48f3ce0afb78eeef3e14c70bcfd7c5f0191c0000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
}

View File

@ -0,0 +1,7 @@
{
"network": "main",
"height": 1180000,
"hash": "0000000000521c0d55ce1765092caff595acb5d546147b192fa9272051f55f42",
"time": 1615778593,
"tree": "0102a70ba9e31d6c24be0fc283577072d815d418da5e1b14cc81923f7bed308460016d9d5c674c15bdaec54c70d528e94be910994213683e3aac2fc94092fd8b4a5b1301dce7f293aee6c2769fe616dd47d46e79b51568c8bc08c67198b20d28eaf12c6f000001ff83e392690a332103433465b2034df2ab6cf35c164149a3951bf0d2bcf2a96601d019ed97502d718643c32851eb1acf6307861a3fe0ce3174697b0c2df4568568011d8eb058dd0a73a4314e04f12a6de50dd18879ee891db5a20c890e1c707f6f01000001cda4d5ff76022119fed8ffb94b8d3a26a0db37a1a886a0f31a57d1c0ce03f106014fb59c2d5dd4cc176d226c57b48d4dfc4d200088d5b69cce675f84e885ee5c1b017d5b561bf80be788ebf12e901e4c544cad95e24d0b21e6145e1718ec9dbfe91101678fbb171e5715c63bfc888d345e755c69c6dbfc2818f05b6e6ca32211ffd44400000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
}

View File

@ -0,0 +1,7 @@
{
"network": "main",
"height": 1190000,
"hash": "00000000019caeb64ab8caa12e1dcdd9a8f391b063ec252887c91526b7ac5e0c",
"time": 1616531745,
"tree": "017ae2fbedf5cad68ee80df0ae9caef9e0168914780bfd14eae016e2fb89068071001301c78a8f9bfddd9a1f0076048c48d1d58298ac6f4368472a39b0b240d540117c4301b58c9284084704437af784307ab0a334dc9c7aef588bf7d26491274d79c4471301b0af0fff110293b555f17d5ced0a598693ff4cde3e680d988c6ccf498846753e01bb9d0f21f621448c03ee49de4ef3bf0faa4844544f9668197ef5921164d2401601a15d695922c5441e80aa770861f91a97dd460561515d32c9d06bd3c6f98ce26f000000014a772e6ce520bcedf07793ded6148fd3415ecbdd89c3efe183b6048f1fb4791c0001e281c5ec71bc1a301ad0d285f6f1aa2552907645b02f9d43160f5354c2be7c63012b4d8d83df48c8b5c35752268eb71a428aa05103809a887fb36519dedbc8de27017b610946256293c523b36cf95ec60f2c346d866d98d1276bbaba22e46815516d000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
}

View File

@ -0,0 +1,7 @@
{
"network": "main",
"height": 1195000,
"hash": "000000000092911166fef6c93bf73b74028232eb4c35e4ec5311879b68e5591d",
"time": 1616908352,
"tree": "01c5abce4daea8caa6672e27d46f092aa950300fa97a80c16c194fe1ff72b05e150013000001d5bbb87f5debb41e36d1a65756a3ba27550a82c84917259ab0a9ee690ec58c1c0000000198cb8ff247cf5cbf818671cba86eccf6a55a9661377f10a0988b2b365da53159015d6b83b48a32db003767a096733b47204700f6c74f079440de990ecf1fc3651c01b96b3b201de78a38a9f88aa45ceeebe5b153843a0cee1856a6334248b287450d01f2d01bb461547e10e4da64a1751ffe65e5cc5cc3e647f0edd6b174b5c7b4156c00000001df26abb60966dedb257d90ef08aa7232474229e08e62ba390336a07c4775a7260001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
}

Some files were not shown because too many files have changed in this diff Show More