Merge branch 'master' into shield-funds-poc
This commit is contained in:
commit
477f7cc69f
|
@ -11,39 +11,38 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
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",
|
||||
"cipher",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"cipher",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
|
@ -117,12 +116,6 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
|
||||
|
||||
[[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"
|
||||
|
@ -131,9 +124,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"
|
||||
|
@ -141,7 +134,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",
|
||||
"ff",
|
||||
|
@ -160,12 +153,24 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.18.4"
|
||||
version = "0.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d2838fdd79e8776dbe07a106c784b0f8dda571a21b2750a092cc4cbaa653c8e"
|
||||
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",
|
||||
]
|
||||
|
||||
|
@ -200,7 +205,7 @@ dependencies = [
|
|||
"block-padding 0.1.5",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array 0.12.3",
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -212,23 +217,14 @@ 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",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -252,7 +248,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",
|
||||
|
@ -270,10 +266,19 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.0"
|
||||
name = "bs58"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
|
||||
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
|
||||
dependencies = [
|
||||
"sha2 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
|
@ -283,9 +288,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
|||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cbindgen"
|
||||
|
@ -307,9 +312,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.41"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
|
||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -317,6 +322,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 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
|
@ -334,9 +348,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"
|
||||
|
@ -352,9 +366,9 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.1"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
|
@ -382,7 +396,7 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.3",
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -423,6 +437,7 @@ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
|||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -474,7 +489,7 @@ 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",
|
||||
]
|
||||
|
@ -492,9 +507,9 @@ dependencies = [
|
|||
|
||||
[[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",
|
||||
|
@ -511,15 +526,15 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
|||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.1.30"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed"
|
||||
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.3"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
@ -592,17 +607,6 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hdwallet"
|
||||
version = "0.2.5"
|
||||
source = "git+https://github.com/nuttycom/hdwallet?rev=72f1f7a56c114eed484cefd6d402b7ef28158712#72f1f7a56c114eed484cefd6d402b7ef28158712"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"rand_core 0.6.2",
|
||||
"ring",
|
||||
"secp256k1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hdwallet"
|
||||
version = "0.3.0"
|
||||
|
@ -635,9 +639,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
|
@ -647,9 +651,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.47"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
|
||||
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -660,7 +664,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",
|
||||
|
@ -689,9 +693,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
|
@ -706,15 +710,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libzcashlc"
|
||||
version = "0.0.5"
|
||||
version = "0.0.6"
|
||||
dependencies = [
|
||||
"base58",
|
||||
"bs58",
|
||||
"bitvec 0.18.5",
|
||||
"bs58 0.3.1",
|
||||
"cbindgen",
|
||||
"failure",
|
||||
"ffi_helpers",
|
||||
"funty",
|
||||
"hdwallet 0.3.0",
|
||||
"hdwallet",
|
||||
"hex",
|
||||
"ripemd160",
|
||||
"secp256k1",
|
||||
|
@ -743,9 +748,9 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
|
@ -753,10 +758,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",
|
||||
|
@ -764,9 +771,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf"
|
||||
checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
|
@ -798,6 +805,12 @@ version = "0.23.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
|
@ -855,24 +868,24 @@ dependencies = [
|
|||
|
||||
[[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"
|
||||
|
||||
[[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",
|
||||
|
@ -889,9 +902,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.4.1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64de9a0c5361e034f1aefc9f71a86871ec870e766fe31a009734a989b329286a"
|
||||
checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
|
@ -1011,13 +1030,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.12"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
|
@ -1057,7 +1076,7 @@ version = "0.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"base64",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
|
@ -1119,18 +1138,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.123"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
|
||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.123"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1139,9 +1158,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.62"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
||||
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1193,9 +1212,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",
|
||||
]
|
||||
|
@ -1269,9 +1288,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.60"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1290,6 +1309,12 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.2.0"
|
||||
|
@ -1315,9 +1340,9 @@ dependencies = [
|
|||
|
||||
[[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",
|
||||
|
@ -1362,9 +1387,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-segmentation"
|
||||
|
@ -1404,9 +1429,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|||
|
||||
[[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 = "wasi"
|
||||
|
@ -1422,9 +1447,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.70"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -1432,9 +1457,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.70"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
|
||||
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
|
@ -1447,9 +1472,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.70"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
||||
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1457,9 +1482,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.70"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
||||
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1470,15 +1495,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.70"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
|
||||
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.47"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
|
||||
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
@ -1514,15 +1539,16 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
|||
|
||||
[[package]]
|
||||
name = "zcash_client_backend"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"base64",
|
||||
"bech32",
|
||||
"bls12_381",
|
||||
"bs58",
|
||||
"bs58 0.4.0",
|
||||
"ff",
|
||||
"group",
|
||||
"hdwallet 0.2.5",
|
||||
"hdwallet",
|
||||
"hex",
|
||||
"jubjub",
|
||||
"nom",
|
||||
|
@ -1540,10 +1566,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_client_sqlite"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"bs58",
|
||||
"bs58 0.4.0",
|
||||
"ff",
|
||||
"group",
|
||||
"jubjub",
|
||||
|
@ -1557,10 +1584,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bitvec",
|
||||
"bitvec 0.18.5",
|
||||
"blake2b_simd",
|
||||
"blake2s_simd",
|
||||
"bls12_381",
|
||||
|
@ -1569,6 +1597,7 @@ dependencies = [
|
|||
"equihash",
|
||||
"ff",
|
||||
"fpe",
|
||||
"funty",
|
||||
"group",
|
||||
"hex",
|
||||
"jubjub",
|
||||
|
@ -1584,7 +1613,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
|
32
Cargo.toml
32
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "libzcashlc"
|
||||
version = "0.0.5"
|
||||
version = "0.0.6"
|
||||
authors = ["Jack Grigg <jack@z.cash>",
|
||||
"Francisco Gindre <francisco@z.cash>",
|
||||
]
|
||||
|
@ -11,11 +11,12 @@ build = "rust/build.rs"
|
|||
failure = "0.1"
|
||||
ffi_helpers = "0.2"
|
||||
hex = "0.4"
|
||||
zcash_client_backend = { version = "0.4", features = ["transparent-inputs"] }
|
||||
zcash_client_sqlite = { version = "0.2.1", features = ["transparent-inputs"] }
|
||||
zcash_primitives = { version = "0.4", features = ["transparent-inputs"] }
|
||||
zcash_client_backend = "0.5"
|
||||
zcash_client_sqlite = "0.3.0"
|
||||
zcash_primitives = "0.5"
|
||||
|
||||
#### Temporary additions: ####################################
|
||||
bitvec = "0.18"
|
||||
base58 = "0.1.0"
|
||||
sha2 = "0.9"
|
||||
bs58 = { version = "0.3", features = ["check"] }
|
||||
|
@ -26,9 +27,8 @@ time = "0.2"
|
|||
funty = "=1.1.0"
|
||||
##############################################################
|
||||
|
||||
|
||||
[dependencies.zcash_proofs]
|
||||
version = "0.4"
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
features = ["local-prover"]
|
||||
|
||||
|
@ -44,16 +44,18 @@ crate-type = ["staticlib"]
|
|||
lto = true
|
||||
|
||||
[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/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 = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_backend" }
|
||||
#zcash_client_sqlite = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_sqlite" }
|
||||
#zcash_primitives = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_primitives" }
|
||||
#zcash_proofs = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_proofs" }
|
||||
|
||||
|
||||
zcash_client_backend = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_backend" }
|
||||
zcash_client_sqlite = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_sqlite" }
|
||||
zcash_primitives = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_primitives" }
|
||||
zcash_proofs = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_proofs" }
|
||||
|
||||
[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_primitives/transparent-inputs"]
|
||||
testnet = ["zcash_client_sqlite/transparent-inputs", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
|
|
@ -0,0 +1,78 @@
|
|||
[package]
|
||||
name = "libzcashlc"
|
||||
version = "0.0.6"
|
||||
authors = ["Jack Grigg <jack@z.cash>",
|
||||
"Francisco Gindre <francisco@z.cash>",
|
||||
]
|
||||
edition = "2018"
|
||||
build = "rust/build.rs"
|
||||
|
||||
[dependencies]
|
||||
failure = "0.1"
|
||||
ffi_helpers = "0.2"
|
||||
hex = "0.4"
|
||||
<<<<<<< HEAD
|
||||
zcash_client_backend = { version = "0.4", features = ["transparent-inputs"] }
|
||||
zcash_client_sqlite = { version = "0.2.1", features = ["transparent-inputs"] }
|
||||
zcash_primitives = { version = "0.4", features = ["transparent-inputs"] }
|
||||
|
||||
=======
|
||||
zcash_client_backend = "0.5"
|
||||
zcash_client_sqlite = "0.3.0"
|
||||
zcash_primitives = "0.5"
|
||||
|
||||
>>>>>>> master
|
||||
#### Temporary additions: ####################################
|
||||
bitvec = "0.18"
|
||||
base58 = "0.1.0"
|
||||
sha2 = "0.9"
|
||||
bs58 = { version = "0.3", features = ["check"] }
|
||||
hdwallet = "0.3.0"
|
||||
ripemd160 = "0.9"
|
||||
<<<<<<< HEAD
|
||||
secp256k1 = "0.19"
|
||||
time = "0.2"
|
||||
=======
|
||||
secp256k1 = "0.17.2"
|
||||
|
||||
# Temporary workaround for https://github.com/myrrlyn/funty/issues/3
|
||||
>>>>>>> master
|
||||
funty = "=1.1.0"
|
||||
##############################################################
|
||||
|
||||
|
||||
[dependencies.zcash_proofs]
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
features = ["local-prover"]
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.14"
|
||||
|
||||
[lib]
|
||||
name = "zcashlc"
|
||||
path = "rust/src/lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
<<<<<<< HEAD
|
||||
[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 = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_backend" }
|
||||
zcash_client_sqlite = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_sqlite" }
|
||||
zcash_primitives = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_primitives" }
|
||||
zcash_proofs = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_proofs" }
|
||||
|
||||
[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_primitives/transparent-inputs"]
|
||||
=======
|
||||
[features]
|
||||
mainnet = ["zcash_client_sqlite/mainnet"]
|
||||
>>>>>>> master
|
|
@ -10,7 +10,7 @@ target 'ZcashLightClientSample' do
|
|||
pod 'PaginatedTableView'
|
||||
pod 'NotificationBubbles'
|
||||
pod 'MnemonicSwift', '~> 2.0.0'
|
||||
pod 'gRPC-Swift-Plugins', '= 1.0.0-alpha.19'
|
||||
pod 'gRPC-Swift-Plugins', '= 1.0.0-alpha.19'
|
||||
target 'ZcashLightClientSampleTests' do
|
||||
use_frameworks!
|
||||
inherit! :search_paths
|
||||
|
|
|
@ -66,10 +66,10 @@ PODS:
|
|||
- SwiftNIOFoundationCompat (< 3, >= 2.22.0)
|
||||
- SwiftNIOTLS (< 3, >= 2.22.0)
|
||||
- SwiftProtobuf (1.12.0)
|
||||
- ZcashLightClientKit (0.9.4):
|
||||
- ZcashLightClientKit (0.10.0):
|
||||
- gRPC-Swift (= 1.0.0-alpha.19)
|
||||
- SQLite.swift (~> 0.12.2)
|
||||
- ZcashLightClientKit/Tests (0.9.4):
|
||||
- ZcashLightClientKit/Tests (0.10.0):
|
||||
- gRPC-Swift (= 1.0.0-alpha.19)
|
||||
- SQLite.swift (~> 0.12.2)
|
||||
|
||||
|
@ -145,8 +145,8 @@ SPEC CHECKSUMS:
|
|||
SwiftNIOTLS: 46bb3a0ff37d6b52ae6baf5207ec3cd411da327c
|
||||
SwiftNIOTransportServices: 801923921fbecdcde1e1c1ff38e812167d01ead1
|
||||
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
|
||||
ZcashLightClientKit: 7f144177deece40fb9075bf6024028026255f75b
|
||||
ZcashLightClientKit: a1a36be74ca95e2802ba3d6bcc40e9b2753eb0da
|
||||
|
||||
PODFILE CHECKSUM: 7d5095283dc02470f40ab06564d94076ba16d570
|
||||
PODFILE CHECKSUM: db5fd49340d00419df0653aac7d56eaeb37d71b6
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
|
|
|
@ -19,44 +19,54 @@ class SampleLogger: ZcashLightClientKit.Logger {
|
|||
case info
|
||||
}
|
||||
|
||||
enum LoggerType {
|
||||
case osLog
|
||||
case printerLog
|
||||
}
|
||||
|
||||
var level: LogLevel
|
||||
init(logLevel: LogLevel) {
|
||||
var loggerType: LoggerType
|
||||
|
||||
init(logLevel: LogLevel, type: LoggerType = .osLog) {
|
||||
self.level = logLevel
|
||||
self.loggerType = type
|
||||
}
|
||||
|
||||
private static let subsystem = Bundle.main.bundleIdentifier!
|
||||
static let oslog = OSLog(subsystem: subsystem, category: "sample-logs")
|
||||
static let oslog = OSLog(subsystem: subsystem, category: "logs")
|
||||
|
||||
func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func debug(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue == LogLevel.debug.rawValue else { return }
|
||||
log(level: "DEBUG 🐞", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func error(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.error.rawValue else { return }
|
||||
log(level: "ERROR 💥", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func warn(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func warn(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.warning.rawValue else { return }
|
||||
log(level: "WARNING ⚠️", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func event(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func event(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.event.rawValue else { return }
|
||||
log(level: "EVENT ⏱", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func info(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.info.rawValue else { return }
|
||||
log(level: "INFO ℹ️", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
private func log(level: String, message: String, file: String, function: String, line: Int) {
|
||||
let fileName = file as NSString
|
||||
|
||||
os_log("[%@] %@ - %@ - Line: %d -> %@", log: Self.oslog, type: .default, level, fileName.lastPathComponent, function, line, message)
|
||||
private func log(level: String, message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
let fileName = (String(describing: file) as NSString).lastPathComponent
|
||||
switch loggerType {
|
||||
case .printerLog:
|
||||
print("[\(level)] \(fileName) - \(function) - line: \(line) -> \(message)")
|
||||
default:
|
||||
os_log("[%{public}@] %{public}@ - %{public}@ - Line: %{public}d -> %{public}@", level, fileName, String(describing: function), line, message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -242,6 +242,15 @@ If you worked with ZcashLightClientKit 0.6.6 or below you might have had to set
|
|||
make sure that the directory that you are working on has the correct rust environment.
|
||||
You can do so by calling `rustup show` in the working directory.
|
||||
|
||||
### Building in Apple Silicon
|
||||
So far we have come up with this set up (april 2021)
|
||||
|
||||
* Clone a terminal and run it in rosetta mode
|
||||
* Clone your Xcode of choice and run it in rosetta mode
|
||||
* Installing the right toolchain for cargo
|
||||
* `rustup toolchain add stable-x86_64-apple-darwin`
|
||||
* `rustup target add aarch64-apple-ios x86_64-apple-darwin x86_64-apple-ios`
|
||||
|
||||
## Versioning
|
||||
|
||||
This project follows [semantic versioning](https://semver.org/) with pre-release versions. An example of a valid version number is `1.0.4-alpha11` denoting the `11th` iteration of the `alpha` pre-release of version `1.0.4`. Stable releases, such as `1.0.4` will not contain any pre-release identifiers. Pre-releases include the following, in order of stability: `alpha`, `beta`, `rc`. Version codes offer a numeric representation of the build name that always increases. The first six significant digits represent the major, minor and patch number (two digits each) and the last 3 significant digits represent the pre-release identifier. The first digit of the identifier signals the build type. Lastly, each new build has a higher version code than all previous builds. The following table breaks this down:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
BASEPATH="${PWD}"
|
||||
TARGET_DIR="target"
|
||||
|
||||
FEATURE_FLAGS=""
|
||||
FEATURE_FLAGS="--features=mainnet"
|
||||
NETWORK_TYPE="TESTNET"
|
||||
FLAVOR_FOLDER="Testnet"
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ fi
|
|||
if is_mainnet; then
|
||||
FEATURE_FLAGS="--features=mainnet"
|
||||
else
|
||||
FEATURE_FLAGS=""
|
||||
FEATURE_FLAGS="--features=testnet"
|
||||
fi
|
||||
|
||||
echo "Building Rust backend"
|
||||
|
@ -42,8 +42,18 @@ else
|
|||
ZCASH_ACTIVE_ARCHITECTURE="aarch64-apple-ios"
|
||||
fi
|
||||
|
||||
echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release"
|
||||
echo "fix 'permission denied issue'"
|
||||
chmod -R +w ${PODS_TARGET_SRCROOT}
|
||||
|
||||
echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release"
|
||||
if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then
|
||||
# Assume we're in Xcode, which means we're probably cross-compiling.
|
||||
# In this case, we need to add an extra library search path for build scripts and proc-macros,
|
||||
# which run on the host instead of the target.
|
||||
# (macOS Big Sur does not have linkable libraries in /usr/lib/.)
|
||||
echo "export LIBRARY_PATH=\"${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}\""
|
||||
export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}"
|
||||
fi
|
||||
if [ ! -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ]; then
|
||||
cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release
|
||||
persist_environment
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'ZcashLightClientKit'
|
||||
s.version = '0.9.4'
|
||||
s.version = '0.10.0'
|
||||
s.summary = 'Zcash Light Client wallet SDK for iOS'
|
||||
|
||||
s.description = <<-DESC
|
||||
|
|
|
@ -78,7 +78,7 @@ class CompactBlockEnhancementOperation: ZcashOperation {
|
|||
}
|
||||
|
||||
func enhance(transaction: TransactionEntity) throws {
|
||||
LoggerProxy.debug("Zoom.... Enhance... Tx: \(transaction.transactionId.toHexStringTxId()) Block: \(String(describing: transaction.minedHeight))")
|
||||
LoggerProxy.debug("Zoom.... Enhance... Tx: \(transaction.transactionId.toHexStringTxId())")
|
||||
|
||||
let tx = try downloader.fetchTransaction(txId: transaction.transactionId)
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ public class CompactBlockProcessor {
|
|||
private var downloader: CompactBlockDownloading
|
||||
private var transactionRepository: TransactionRepository
|
||||
private var rustBackend: ZcashRustBackendWelding.Type
|
||||
private var config: Configuration = Configuration.standard
|
||||
private(set) var config: Configuration = Configuration.standard
|
||||
private var queue: OperationQueue = {
|
||||
let q = OperationQueue()
|
||||
q.name = "CompactBlockProcessorQueue"
|
||||
|
@ -370,6 +370,19 @@ public class CompactBlockProcessor {
|
|||
self.state = .stopped
|
||||
}
|
||||
|
||||
public func rewindTo(_ height: BlockHeight) throws {
|
||||
self.stop()
|
||||
|
||||
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(height)) else {
|
||||
fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)"))
|
||||
return
|
||||
}
|
||||
|
||||
// clear cache
|
||||
try downloader.rewind(to: height)
|
||||
}
|
||||
|
||||
|
||||
private func nextBatch() throws {
|
||||
// get latest block height
|
||||
|
||||
|
@ -468,9 +481,7 @@ public class CompactBlockProcessor {
|
|||
}
|
||||
|
||||
validateChainOperation.startedHandler = { [weak self] in
|
||||
|
||||
self?.state = .validating
|
||||
|
||||
}
|
||||
|
||||
let scanBlocksOperation = CompactBlockScanningOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb)
|
||||
|
|
|
@ -56,6 +56,18 @@ public extension TransactionEntity {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
var anchor: BlockHeight? {
|
||||
if let minedHeight = self.minedHeight, minedHeight != -1 {
|
||||
return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
|
||||
}
|
||||
|
||||
if let expiryHeight = self.expiryHeight, expiryHeight != -1 {
|
||||
return max(expiryHeight - ZcashSDK.EXPIRY_OFFSET - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
/**
|
||||
Abstract representation of all transaction types
|
||||
|
|
|
@ -54,7 +54,6 @@ public protocol ZcashRustBackendWelding {
|
|||
*/
|
||||
static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool
|
||||
|
||||
|
||||
/**
|
||||
initialize the accounts table from a given seed and a number of accounts
|
||||
- Parameters:
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) 2019-2020 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = ".;walletrpc";
|
||||
option swift_prefix = "";
|
||||
import "service.proto";
|
||||
|
||||
message DarksideMetaState {
|
||||
int32 saplingActivation = 1;
|
||||
string branchID = 2;
|
||||
string chainName = 3;
|
||||
}
|
||||
|
||||
// A block is a hex-encoded string.
|
||||
message DarksideBlock {
|
||||
string block = 1;
|
||||
}
|
||||
|
||||
// DarksideBlocksURL is typically something like:
|
||||
// https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/before-reorg.txt
|
||||
message DarksideBlocksURL {
|
||||
string url = 1;
|
||||
}
|
||||
|
||||
// DarksideTransactionsURL refers to an HTTP source that contains a list
|
||||
// of hex-encoded transactions, one per line, that are to be associated
|
||||
// with the given height (fake-mined into the block at that height)
|
||||
message DarksideTransactionsURL {
|
||||
int32 height = 1;
|
||||
string url = 2;
|
||||
}
|
||||
|
||||
message DarksideHeight {
|
||||
int32 height = 1;
|
||||
}
|
||||
|
||||
message DarksideEmptyBlocks {
|
||||
int32 height = 1;
|
||||
int32 nonce = 2;
|
||||
int32 count = 3;
|
||||
}
|
||||
|
||||
// Darksidewalletd maintains two staging areas, blocks and transactions. The
|
||||
// Stage*() gRPCs add items to the staging area; ApplyStaged() "applies" everything
|
||||
// in the staging area to the working (operational) state that the mock zcashd
|
||||
// serves; transactions are placed into their corresponding blocks (by height).
|
||||
service DarksideStreamer {
|
||||
// Reset reverts all darksidewalletd state (active block range, latest height,
|
||||
// staged blocks and transactions) and lightwalletd state (cache) to empty,
|
||||
// the same as the initial state. This occurs synchronously and instantaneously;
|
||||
// no reorg happens in lightwalletd. This is good to do before each independent
|
||||
// test so that no state leaks from one test to another.
|
||||
// Also sets (some of) the values returned by GetLightdInfo(). The Sapling
|
||||
// activation height specified here must be where the block range starts.
|
||||
rpc Reset(DarksideMetaState) returns (Empty) {}
|
||||
|
||||
// StageBlocksStream accepts a list of blocks and saves them into the blocks
|
||||
// staging area until ApplyStaged() is called; there is no immediate effect on
|
||||
// the mock zcashd. Blocks are hex-encoded. Order is important, see ApplyStaged.
|
||||
rpc StageBlocksStream(stream DarksideBlock) returns (Empty) {}
|
||||
|
||||
// StageBlocks is the same as StageBlocksStream() except the blocks are fetched
|
||||
// from the given URL. Blocks are one per line, hex-encoded (not JSON).
|
||||
rpc StageBlocks(DarksideBlocksURL) returns (Empty) {}
|
||||
|
||||
// StageBlocksCreate is like the previous two, except it creates 'count'
|
||||
// empty blocks at consecutive heights starting at height 'height'. The
|
||||
// 'nonce' is part of the header, so it contributes to the block hash; this
|
||||
// lets you create identical blocks (same transactions and height), but with
|
||||
// different hashes.
|
||||
rpc StageBlocksCreate(DarksideEmptyBlocks) returns (Empty) {}
|
||||
|
||||
// StageTransactionsStream stores the given transaction-height pairs in the
|
||||
// staging area until ApplyStaged() is called. Note that these transactions
|
||||
// are not returned by the production GetTransaction() gRPC until they
|
||||
// appear in a "mined" block (contained in the active blockchain presented
|
||||
// by the mock zcashd).
|
||||
rpc StageTransactionsStream(stream RawTransaction) returns (Empty) {}
|
||||
|
||||
// StageTransactions is the same except the transactions are fetched from
|
||||
// the given url. They are all staged into the block at the given height.
|
||||
// Staging transactions to different heights requires multiple calls.
|
||||
rpc StageTransactions(DarksideTransactionsURL) returns (Empty) {}
|
||||
|
||||
// ApplyStaged iterates the list of blocks that were staged by the
|
||||
// StageBlocks*() gRPCs, in the order they were staged, and "merges" each
|
||||
// into the active, working blocks list that the mock zcashd is presenting
|
||||
// to lightwalletd. Even as each block is applied, the active list can't
|
||||
// have gaps; if the active block range is 1000-1006, and the staged block
|
||||
// range is 1003-1004, the resulting range is 1000-1004, with 1000-1002
|
||||
// unchanged, blocks 1003-1004 from the new range, and 1005-1006 dropped.
|
||||
//
|
||||
// After merging all blocks, ApplyStaged() appends staged transactions (in
|
||||
// the order received) into each one's corresponding (by height) block
|
||||
// The staging area is then cleared.
|
||||
//
|
||||
// The argument specifies the latest block height that mock zcashd reports
|
||||
// (i.e. what's returned by GetLatestBlock). Note that ApplyStaged() can
|
||||
// also be used to simply advance the latest block height presented by mock
|
||||
// zcashd. That is, there doesn't need to be anything in the staging area.
|
||||
rpc ApplyStaged(DarksideHeight) returns (Empty) {}
|
||||
|
||||
// Calls to the production gRPC SendTransaction() store the transaction in
|
||||
// a separate area (not the staging area); this method returns all transactions
|
||||
// in this separate area, which is then cleared. The height returned
|
||||
// with each transaction is -1 (invalid) since these transactions haven't
|
||||
// been mined yet. The intention is that the transactions returned here can
|
||||
// then, for example, be given to StageTransactions() to get them "mined"
|
||||
// into a specified block on the next ApplyStaged().
|
||||
rpc GetIncomingTransactions(Empty) returns (stream RawTransaction) {}
|
||||
|
||||
// Clear the incoming transaction pool.
|
||||
rpc ClearIncomingTransactions(Empty) returns (Empty) {}
|
||||
}
|
|
@ -34,7 +34,7 @@ message TxFilter {
|
|||
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||
// the block height in which the transaction was included.
|
||||
message RawTransaction {
|
||||
bytes data = 1; // exact data returned by zcash 'getrawtransaction'
|
||||
bytes data = 1; // exact data returned by Zcash 'getrawtransaction'
|
||||
uint64 height = 2; // height that the transaction was mined (or -1)
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,9 @@ message LightdInfo {
|
|||
string branch = 9;
|
||||
string buildDate = 10;
|
||||
string buildUser = 11;
|
||||
uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing
|
||||
string zcashdBuild = 13; // example: "v4.1.1-877212414"
|
||||
string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/"
|
||||
}
|
||||
|
||||
// TransparentAddressBlockFilter restricts the results to the given address
|
||||
|
@ -104,7 +107,7 @@ message Exclude {
|
|||
repeated bytes txid = 1;
|
||||
}
|
||||
|
||||
// The TreeState is derived from the zcash z_gettreestate rpc.
|
||||
// The TreeState is derived from the Zcash z_gettreestate rpc.
|
||||
message TreeState {
|
||||
string network = 1; // "main" or "test"
|
||||
uint64 height = 2;
|
||||
|
@ -139,7 +142,7 @@ service CompactTxStreamer {
|
|||
|
||||
// Return the requested full (not compact) transaction (as from zcashd)
|
||||
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
|
||||
// Submit the given transaction to the zcash network
|
||||
// Submit the given transaction to the Zcash network
|
||||
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
|
||||
|
||||
// Return the txids corresponding to the given t-address within the given block range
|
||||
|
@ -159,7 +162,7 @@ service CompactTxStreamer {
|
|||
rpc GetMempoolTx(Exclude) returns (stream CompactTx) {}
|
||||
|
||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||
// See section 3.7 of the zcash protocol specification. It returns several other useful
|
||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||
// values also (even though they can be obtained using GetBlock).
|
||||
// The block can be specified by either height or hash.
|
||||
rpc GetTreeState(BlockID) returns (TreeState) {}
|
||||
|
|
|
@ -175,7 +175,7 @@ extension CompactTxStreamerClientProtocol {
|
|||
)
|
||||
}
|
||||
|
||||
/// Submit the given transaction to the zcash network
|
||||
/// Submit the given transaction to the Zcash network
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to SendTransaction.
|
||||
|
@ -275,7 +275,7 @@ extension CompactTxStreamerClientProtocol {
|
|||
}
|
||||
|
||||
/// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||
/// See section 3.7 of the zcash protocol specification. It returns several other useful
|
||||
/// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||
/// values also (even though they can be obtained using GetBlock).
|
||||
/// The block can be specified by either height or hash.
|
||||
///
|
||||
|
|
|
@ -111,7 +111,7 @@ struct RawTransaction {
|
|||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// exact data returned by zcash 'getrawtransaction'
|
||||
/// exact data returned by Zcash 'getrawtransaction'
|
||||
var data: Data = SwiftProtobuf.Internal.emptyData
|
||||
|
||||
/// height that the transaction was mined (or -1)
|
||||
|
@ -195,6 +195,15 @@ struct LightdInfo {
|
|||
|
||||
var buildUser: String = String()
|
||||
|
||||
/// less than tip height if zcashd is syncing
|
||||
var estimatedHeight: UInt64 = 0
|
||||
|
||||
/// example: "v4.1.1-877212414"
|
||||
var zcashdBuild: String = String()
|
||||
|
||||
/// example: "/MagicBean:4.1.1/"
|
||||
var zcashdSubversion: String = String()
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
@ -307,7 +316,7 @@ struct Exclude {
|
|||
init() {}
|
||||
}
|
||||
|
||||
/// The TreeState is derived from the zcash z_gettreestate rpc.
|
||||
/// The TreeState is derived from the Zcash z_gettreestate rpc.
|
||||
struct TreeState {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -618,6 +627,9 @@ extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
9: .same(proto: "branch"),
|
||||
10: .same(proto: "buildDate"),
|
||||
11: .same(proto: "buildUser"),
|
||||
12: .same(proto: "estimatedHeight"),
|
||||
13: .same(proto: "zcashdBuild"),
|
||||
14: .same(proto: "zcashdSubversion"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
@ -634,6 +646,9 @@ extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
case 9: try decoder.decodeSingularStringField(value: &self.branch)
|
||||
case 10: try decoder.decodeSingularStringField(value: &self.buildDate)
|
||||
case 11: try decoder.decodeSingularStringField(value: &self.buildUser)
|
||||
case 12: try decoder.decodeSingularUInt64Field(value: &self.estimatedHeight)
|
||||
case 13: try decoder.decodeSingularStringField(value: &self.zcashdBuild)
|
||||
case 14: try decoder.decodeSingularStringField(value: &self.zcashdSubversion)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
@ -673,6 +688,15 @@ extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
if !self.buildUser.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.buildUser, fieldNumber: 11)
|
||||
}
|
||||
if self.estimatedHeight != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.estimatedHeight, fieldNumber: 12)
|
||||
}
|
||||
if !self.zcashdBuild.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.zcashdBuild, fieldNumber: 13)
|
||||
}
|
||||
if !self.zcashdSubversion.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.zcashdSubversion, fieldNumber: 14)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -688,6 +712,9 @@ extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
if lhs.branch != rhs.branch {return false}
|
||||
if lhs.buildDate != rhs.buildDate {return false}
|
||||
if lhs.buildUser != rhs.buildUser {return false}
|
||||
if lhs.estimatedHeight != rhs.estimatedHeight {return false}
|
||||
if lhs.zcashdBuild != rhs.zcashdBuild {return false}
|
||||
if lhs.zcashdSubversion != rhs.zcashdSubversion {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ public enum SynchronizerError: Error {
|
|||
case uncategorized(underlyingError: Error)
|
||||
case criticalError
|
||||
case parameterMissing(underlyingError: Error)
|
||||
case rewindError(underlyingError: Error)
|
||||
case rewindErrorUnknownArchorHeight
|
||||
}
|
||||
|
||||
public enum ShieldFundsError: Error {
|
||||
|
@ -211,6 +213,15 @@ public protocol Synchronizer {
|
|||
*/
|
||||
func getShieldedVerifiedBalance(accountIndex: Int) -> Int64
|
||||
|
||||
|
||||
/**
|
||||
Stops the synchronizer and rescans the known blocks with the current keys.
|
||||
- Parameter policy: the rewind policy
|
||||
- Throws rewindErrorUnknownArchorHeight when the rewind points to an invalid height
|
||||
- Throws rewindError for other errors
|
||||
- Note rewind does not trigger notifications as a reorg would. You need to restart the synchronizer afterwards
|
||||
*/
|
||||
func rewind(_ policy: RewindPolicy) throws
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,3 +262,17 @@ public enum TransactionKind {
|
|||
case received
|
||||
case all
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Type of rewind available
|
||||
birthday: rewinds the local state to this wallet's birthday
|
||||
height: rewinds to an arbitrary blockheight
|
||||
transaction: rewinds to the mined height of the provided transaction.
|
||||
*/
|
||||
|
||||
public enum RewindPolicy {
|
||||
case birthday
|
||||
case height(blockheight: BlockHeight)
|
||||
case transaction(_ transaction: TransactionEntity)
|
||||
}
|
||||
|
|
|
@ -529,6 +529,37 @@ public class SDKSynchronizer: Synchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
public func rewind(_ policy: RewindPolicy) throws {
|
||||
self.stop()
|
||||
|
||||
var height: BlockHeight?
|
||||
switch policy {
|
||||
case .birthday:
|
||||
let birthday = self.blockProcessor.config.walletBirthday
|
||||
height = birthday
|
||||
|
||||
case .height(let rewindHeight):
|
||||
height = rewindHeight
|
||||
|
||||
case .transaction(let tx):
|
||||
guard let txHeight = tx.anchor else {
|
||||
throw SynchronizerError.rewindErrorUnknownArchorHeight
|
||||
}
|
||||
height = txHeight
|
||||
}
|
||||
|
||||
guard let h = height else {
|
||||
throw SynchronizerError.rewindErrorUnknownArchorHeight
|
||||
}
|
||||
|
||||
do {
|
||||
try self.blockProcessor.rewindTo(h)
|
||||
try self.transactionManager.handleReorg(at: h)
|
||||
} catch {
|
||||
throw SynchronizerError.rewindError(underlyingError: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: notify state
|
||||
private func notify(progress: Float, height: BlockHeight) {
|
||||
NotificationCenter.default.post(name: Notification.Name.synchronizerProgressUpdated, object: self, userInfo: [
|
||||
|
|
|
@ -12,15 +12,15 @@ import Foundation
|
|||
*/
|
||||
public protocol Logger {
|
||||
|
||||
func debug(_ message: String, file: String, function: String, line: Int)
|
||||
func debug(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
||||
func info(_ message: String, file: String, function: String, line: Int)
|
||||
func info(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
||||
func event(_ message: String, file: String, function: String, line: Int)
|
||||
func event(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
||||
func warn(_ message: String, file: String, function: String, line: Int)
|
||||
func warn(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
||||
func error(_ message: String, file: String, function: String, line: Int)
|
||||
func error(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
||||
}
|
||||
|
||||
|
@ -28,23 +28,23 @@ var logger: Logger?
|
|||
|
||||
class LoggerProxy {
|
||||
|
||||
static func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
static func debug(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
logger?.debug(message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
static func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
static func info(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
logger?.info(message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
static func event(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
static func event(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
logger?.event(message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
static func warn(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
static func warn(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
logger?.warn(message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
static func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
static func error(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
logger?.error(message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
|
|
|
@ -223,6 +223,9 @@ bool zcashlc_is_valid_shielded_address(const char *address);
|
|||
*/
|
||||
bool zcashlc_is_valid_transparent_address(const char *address);
|
||||
|
||||
/**
|
||||
* returns whether the given viewing key is valid or not
|
||||
*/
|
||||
bool zcashlc_is_valid_viewing_key(const char *key);
|
||||
|
||||
/**
|
||||
|
|
|
@ -418,7 +418,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
firstSyncExpectation.fulfill()
|
||||
}, error: self.handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 5)
|
||||
wait(for: [firstSyncExpectation], timeout: 10)
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -30,6 +30,417 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
verify that when sending the maximum amount, the transactions are broadcasted properly
|
||||
*/
|
||||
func testMaxAmountSend() throws {
|
||||
let notificationHandler = SDKSynchonizerListener()
|
||||
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
||||
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
||||
|
||||
// 0 subscribe to updated transactions events
|
||||
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
||||
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee())
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
guard let spendingKey = coordinator.spendingKeys?.first else {
|
||||
XCTFail("failed to create spending keys")
|
||||
return
|
||||
}
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(spendingKey: spendingKey,
|
||||
zatoshi: maxBalance,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0) { result in
|
||||
switch result {
|
||||
case .failure(let error):
|
||||
XCTFail("sendToAddress failed: \(error)")
|
||||
case .success(let transaction):
|
||||
pendingTx = transaction
|
||||
}
|
||||
self.sentTransactionExpectation.fulfill()
|
||||
}
|
||||
wait(for: [sentTransactionExpectation], timeout: 20)
|
||||
guard let pendingTx = pendingTx else {
|
||||
XCTFail("transaction creation failed")
|
||||
return
|
||||
}
|
||||
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTAssertNotNil(tx.rawTransactionId)
|
||||
XCTAssertNotNil(pendingTx.rawTransactionId)
|
||||
XCTAssertEqual(tx.rawTransactionId, pendingTx.rawTransactionId)
|
||||
transactionMinedExpectation.fulfill()
|
||||
}
|
||||
|
||||
|
||||
// 5 apply to height
|
||||
// 6 mine the block
|
||||
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
||||
XCTFail("no incoming transaction after")
|
||||
return
|
||||
}
|
||||
|
||||
let latestHeight = try coordinator.latestHeight()
|
||||
let sentTxHeight = latestHeight + 1
|
||||
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
let foundTx = txs.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(foundTx)
|
||||
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
||||
|
||||
foundTransactionsExpectation.fulfill()
|
||||
}
|
||||
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
||||
sleep(1)
|
||||
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight)
|
||||
sleep(2) // add enhance breakpoint here
|
||||
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
let p = synchronizer.pendingTransactions.first(where: {$0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(p, "pending transaction should have been mined by now")
|
||||
XCTAssertTrue(p?.isMined ?? false)
|
||||
XCTAssertEqual(p?.minedHeight, sentTxHeight)
|
||||
mineExpectation.fulfill()
|
||||
|
||||
}, error: { (error) in
|
||||
guard let e = error else {
|
||||
XCTFail("unknown error syncing after sending transaction")
|
||||
return
|
||||
}
|
||||
|
||||
XCTFail("Error: \(e)")
|
||||
})
|
||||
|
||||
wait(for: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
||||
|
||||
// 7 advance to confirmation
|
||||
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight + 10)
|
||||
|
||||
sleep(2)
|
||||
|
||||
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
||||
}
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTFail("We shouldn't find any mined transactions at this point but found \(tx)")
|
||||
}
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
confirmExpectation.fulfill()
|
||||
}, error: { e in
|
||||
self.handleError(e)
|
||||
})
|
||||
|
||||
wait(for: [confirmExpectation], timeout: 5)
|
||||
|
||||
let confirmedPending = try coordinator.synchronizer.allPendingTransactions().first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
verify that when sending the maximum amount minus one zatoshi, the transactions are broadcasted properly
|
||||
*/
|
||||
func testMaxAmountMinusOneSend() throws {
|
||||
let notificationHandler = SDKSynchonizerListener()
|
||||
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
||||
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
||||
|
||||
// 0 subscribe to updated transactions events
|
||||
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
||||
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalanceMinusOne = verifiedBalance - Int64(ZcashSDK.defaultFee()) - 1
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
guard let spendingKey = coordinator.spendingKeys?.first else {
|
||||
XCTFail("failed to create spending keys")
|
||||
return
|
||||
}
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(spendingKey: spendingKey,
|
||||
zatoshi: maxBalanceMinusOne,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0) { result in
|
||||
switch result {
|
||||
case .failure(let error):
|
||||
XCTFail("sendToAddress failed: \(error)")
|
||||
case .success(let transaction):
|
||||
pendingTx = transaction
|
||||
}
|
||||
self.sentTransactionExpectation.fulfill()
|
||||
}
|
||||
wait(for: [sentTransactionExpectation], timeout: 20)
|
||||
guard let pendingTx = pendingTx else {
|
||||
XCTFail("transaction creation failed")
|
||||
return
|
||||
}
|
||||
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTAssertNotNil(tx.rawTransactionId)
|
||||
XCTAssertNotNil(pendingTx.rawTransactionId)
|
||||
XCTAssertEqual(tx.rawTransactionId, pendingTx.rawTransactionId)
|
||||
transactionMinedExpectation.fulfill()
|
||||
}
|
||||
|
||||
|
||||
// 5 apply to height
|
||||
// 6 mine the block
|
||||
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
||||
XCTFail("no incoming transaction after")
|
||||
return
|
||||
}
|
||||
|
||||
let latestHeight = try coordinator.latestHeight()
|
||||
let sentTxHeight = latestHeight + 1
|
||||
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
let foundTx = txs.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(foundTx)
|
||||
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
||||
|
||||
foundTransactionsExpectation.fulfill()
|
||||
}
|
||||
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
||||
sleep(1)
|
||||
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight)
|
||||
sleep(2) // add enhance breakpoint here
|
||||
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
let p = synchronizer.pendingTransactions.first(where: {$0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(p, "pending transaction should have been mined by now")
|
||||
XCTAssertTrue(p?.isMined ?? false)
|
||||
XCTAssertEqual(p?.minedHeight, sentTxHeight)
|
||||
mineExpectation.fulfill()
|
||||
|
||||
}, error: { (error) in
|
||||
guard let e = error else {
|
||||
XCTFail("unknown error syncing after sending transaction")
|
||||
return
|
||||
}
|
||||
|
||||
XCTFail("Error: \(e)")
|
||||
})
|
||||
|
||||
wait(for: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
||||
|
||||
// 7 advance to confirmation
|
||||
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight + 10)
|
||||
|
||||
sleep(2)
|
||||
|
||||
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
||||
}
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTFail("We shouldn't find any mined transactions at this point but found \(tx)")
|
||||
}
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
confirmExpectation.fulfill()
|
||||
}, error: { e in
|
||||
self.handleError(e)
|
||||
})
|
||||
|
||||
wait(for: [confirmExpectation], timeout: 5)
|
||||
|
||||
let confirmedPending = try coordinator.synchronizer.allPendingTransactions().first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 1)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 1)
|
||||
}
|
||||
|
||||
/**
|
||||
verify that when sending the a no change transaction, the transactions are broadcasted properly
|
||||
*/
|
||||
func testSingleNoteNoChangeTransaction() throws {
|
||||
let notificationHandler = SDKSynchonizerListener()
|
||||
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
||||
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
||||
|
||||
// 0 subscribe to updated transactions events
|
||||
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
||||
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalanceMinusOne = 100000 - ZcashSDK.defaultFee()
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
guard let spendingKey = coordinator.spendingKeys?.first else {
|
||||
XCTFail("failed to create spending keys")
|
||||
return
|
||||
}
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(spendingKey: spendingKey,
|
||||
zatoshi: maxBalanceMinusOne,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0) { result in
|
||||
switch result {
|
||||
case .failure(let error):
|
||||
XCTFail("sendToAddress failed: \(error)")
|
||||
case .success(let transaction):
|
||||
pendingTx = transaction
|
||||
}
|
||||
self.sentTransactionExpectation.fulfill()
|
||||
}
|
||||
wait(for: [sentTransactionExpectation], timeout: 20)
|
||||
guard let pendingTx = pendingTx else {
|
||||
XCTFail("transaction creation failed")
|
||||
return
|
||||
}
|
||||
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTAssertNotNil(tx.rawTransactionId)
|
||||
XCTAssertNotNil(pendingTx.rawTransactionId)
|
||||
XCTAssertEqual(tx.rawTransactionId, pendingTx.rawTransactionId)
|
||||
transactionMinedExpectation.fulfill()
|
||||
}
|
||||
|
||||
|
||||
// 5 apply to height
|
||||
// 6 mine the block
|
||||
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
||||
XCTFail("no incoming transaction after")
|
||||
return
|
||||
}
|
||||
|
||||
let latestHeight = try coordinator.latestHeight()
|
||||
let sentTxHeight = latestHeight + 1
|
||||
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
let foundTx = txs.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(foundTx)
|
||||
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
||||
|
||||
foundTransactionsExpectation.fulfill()
|
||||
}
|
||||
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
||||
sleep(1)
|
||||
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight)
|
||||
sleep(2) // add enhance breakpoint here
|
||||
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
let p = synchronizer.pendingTransactions.first(where: {$0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(p, "pending transaction should have been mined by now")
|
||||
XCTAssertTrue(p?.isMined ?? false)
|
||||
XCTAssertEqual(p?.minedHeight, sentTxHeight)
|
||||
mineExpectation.fulfill()
|
||||
|
||||
}, error: { (error) in
|
||||
guard let e = error else {
|
||||
XCTFail("unknown error syncing after sending transaction")
|
||||
return
|
||||
}
|
||||
|
||||
XCTFail("Error: \(e)")
|
||||
})
|
||||
|
||||
wait(for: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
||||
|
||||
// 7 advance to confirmation
|
||||
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight + 10)
|
||||
|
||||
sleep(2)
|
||||
|
||||
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
||||
}
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTFail("We shouldn't find any mined transactions at this point but found \(tx)")
|
||||
}
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
confirmExpectation.fulfill()
|
||||
}, error: { e in
|
||||
self.handleError(e)
|
||||
})
|
||||
|
||||
wait(for: [confirmExpectation], timeout: 5)
|
||||
|
||||
let confirmedPending = try coordinator.synchronizer.allPendingTransactions().first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 100000)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 100000)
|
||||
}
|
||||
/**
|
||||
|
||||
Verify available balance is correct in all wallet states during a send
|
||||
|
@ -103,6 +514,7 @@ class BalanceTests: XCTestCase {
|
|||
XCTFail("no incoming transaction after")
|
||||
return
|
||||
}
|
||||
|
||||
let latestHeight = try coordinator.latestHeight()
|
||||
let sentTxHeight = latestHeight + 1
|
||||
try coordinator.stageBlockCreate(height: sentTxHeight)
|
||||
|
@ -615,3 +1027,39 @@ class BalanceTests: XCTestCase {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class SDKSynchonizerListener {
|
||||
var transactionsFound: (([ConfirmedTransactionEntity]) -> ())?
|
||||
var synchronizerMinedTransaction: ((PendingTransactionEntity) -> ())?
|
||||
|
||||
func subscribeToSynchronizer(_ synchronizer: SDKSynchronizer) {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(txFound(_:)), name: .synchronizerFoundTransactions, object: synchronizer)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(txMined(_:)), name: .synchronizerMinedTransaction, object: synchronizer)
|
||||
}
|
||||
|
||||
func unsubscribe() {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
@objc func txFound(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let txs = notification.userInfo?[SDKSynchronizer.NotificationKeys.foundTransactions] as? [ConfirmedTransactionEntity] else {
|
||||
XCTFail("expected [ConfirmedTransactionEntity] array")
|
||||
return
|
||||
}
|
||||
|
||||
self?.transactionsFound?(txs)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func txMined(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let tx = notification.userInfo?[SDKSynchronizer.NotificationKeys.minedTransaction] as? PendingTransactionEntity else {
|
||||
XCTFail("expected transaction")
|
||||
return
|
||||
}
|
||||
|
||||
self?.synchronizerMinedTransaction?(tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,337 @@
|
|||
//
|
||||
// XCTRewindRescanTests.swift
|
||||
// ZcashLightClientKit-Unit-Tests
|
||||
//
|
||||
// Created by Francisco Gindre on 3/25/21.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import ZcashLightClientKit
|
||||
class RewindRescanTests: XCTestCase {
|
||||
var 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" //TODO: Parameterize this from environment?
|
||||
|
||||
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment
|
||||
|
||||
let sendAmount: Int64 = 1000
|
||||
var birthday: BlockHeight = 663150
|
||||
let defaultLatestHeight: BlockHeight = 663175
|
||||
var coordinator: TestCoordinator!
|
||||
var syncedExpectation = XCTestExpectation(description: "synced")
|
||||
var sentTransactionExpectation = XCTestExpectation(description: "sent")
|
||||
var expectedReorgHeight: BlockHeight = 665188
|
||||
var expectedRewindHeight: BlockHeight = 665188
|
||||
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
|
||||
override func setUpWithError() throws {
|
||||
|
||||
coordinator = try TestCoordinator(
|
||||
seed: seedPhrase,
|
||||
walletBirthday: birthday,
|
||||
channelProvider: ChannelProvider()
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150)
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
try coordinator.stop()
|
||||
try? FileManager.default.removeItem(at: coordinator.databases.cacheDB)
|
||||
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
|
||||
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
|
||||
}
|
||||
|
||||
|
||||
func handleError(_ error: Error?) {
|
||||
guard let testError = error else {
|
||||
XCTFail("failed with nil error")
|
||||
return
|
||||
}
|
||||
XCTFail("Failed with error: \(testError)")
|
||||
}
|
||||
|
||||
func testBirthdayRescan() throws {
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 50)
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
// rewind to birthday
|
||||
try coordinator.synchronizer.rewind(.birthday)
|
||||
|
||||
// assert that after the new height is
|
||||
XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),self.birthday)
|
||||
|
||||
// check that the balance is cleared
|
||||
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
|
||||
let secondScanExpectation = XCTestExpectation(description: "rescan")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
secondScanExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [secondScanExpectation], timeout: 12)
|
||||
|
||||
// verify that the balance still adds up
|
||||
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
|
||||
|
||||
}
|
||||
|
||||
|
||||
func testRescanToHeight() throws {
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 50)
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
// rewind to birthday
|
||||
let targetHeight: BlockHeight = 663160
|
||||
try coordinator.synchronizer.rewind(.height(blockheight: targetHeight))
|
||||
|
||||
// assert that after the new height is
|
||||
XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),targetHeight)
|
||||
|
||||
// check that the balance is cleared
|
||||
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
|
||||
let secondScanExpectation = XCTestExpectation(description: "rescan")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
secondScanExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [secondScanExpectation], timeout: 12)
|
||||
|
||||
// verify that the balance still adds up
|
||||
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
|
||||
|
||||
}
|
||||
|
||||
func testRescanToTransaction() throws {
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 50)
|
||||
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
// rewind to transaction
|
||||
guard let transaction = try coordinator.synchronizer.allClearedTransactions().first else {
|
||||
XCTFail("failed to get a transaction to rewind to")
|
||||
return
|
||||
}
|
||||
|
||||
try coordinator.synchronizer.rewind(.transaction(transaction.transactionEntity))
|
||||
|
||||
|
||||
// assert that after the new height is
|
||||
XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),transaction.transactionEntity.anchor)
|
||||
|
||||
let secondScanExpectation = XCTestExpectation(description: "rescan")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
secondScanExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [secondScanExpectation], timeout: 12)
|
||||
|
||||
// verify that the balance still adds up
|
||||
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
|
||||
|
||||
}
|
||||
|
||||
func testRewindAfterSendingTransaction() throws {
|
||||
let notificationHandler = SDKSynchonizerListener()
|
||||
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
||||
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
||||
|
||||
// 0 subscribe to updated transactions events
|
||||
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
||||
// 1 sync and get spendable funds
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
||||
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee())
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
guard let spendingKey = coordinator.spendingKeys?.first else {
|
||||
XCTFail("failed to create spending keys")
|
||||
return
|
||||
}
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(spendingKey: spendingKey,
|
||||
zatoshi: maxBalance,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0) { result in
|
||||
switch result {
|
||||
case .failure(let error):
|
||||
XCTFail("sendToAddress failed: \(error)")
|
||||
case .success(let transaction):
|
||||
pendingTx = transaction
|
||||
}
|
||||
self.sentTransactionExpectation.fulfill()
|
||||
}
|
||||
wait(for: [sentTransactionExpectation], timeout: 20)
|
||||
guard let pendingTx = pendingTx else {
|
||||
XCTFail("transaction creation failed")
|
||||
return
|
||||
}
|
||||
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTAssertNotNil(tx.rawTransactionId)
|
||||
XCTAssertNotNil(pendingTx.rawTransactionId)
|
||||
XCTAssertEqual(tx.rawTransactionId, pendingTx.rawTransactionId)
|
||||
transactionMinedExpectation.fulfill()
|
||||
}
|
||||
|
||||
|
||||
// 5 apply to height
|
||||
// 6 mine the block
|
||||
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
||||
XCTFail("no incoming transaction after")
|
||||
return
|
||||
}
|
||||
|
||||
let latestHeight = try coordinator.latestHeight()
|
||||
let sentTxHeight = latestHeight + 1
|
||||
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
let foundTx = txs.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(foundTx)
|
||||
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
||||
|
||||
foundTransactionsExpectation.fulfill()
|
||||
}
|
||||
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
||||
sleep(1)
|
||||
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight)
|
||||
sleep(2)
|
||||
|
||||
|
||||
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
||||
|
||||
try coordinator.sync(completion: { (synchronizer) in
|
||||
let p = synchronizer.pendingTransactions.first(where: {$0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
XCTAssertNotNil(p, "pending transaction should have been mined by now")
|
||||
XCTAssertTrue(p?.isMined ?? false)
|
||||
XCTAssertEqual(p?.minedHeight, sentTxHeight)
|
||||
mineExpectation.fulfill()
|
||||
|
||||
}, error: { (error) in
|
||||
guard let e = error else {
|
||||
XCTFail("unknown error syncing after sending transaction")
|
||||
return
|
||||
}
|
||||
|
||||
XCTFail("Error: \(e)")
|
||||
})
|
||||
|
||||
wait(for: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
||||
|
||||
// 7 advance to confirmation
|
||||
|
||||
try coordinator.applyStaged(blockheight: sentTxHeight + 10)
|
||||
|
||||
sleep(2)
|
||||
|
||||
// rewind 5 blocks prior to sending
|
||||
|
||||
try coordinator.synchronizer.rewind(.height(blockheight: sentTxHeight - 5))
|
||||
|
||||
guard let np = try coordinator.synchronizer.allPendingTransactions().first(where: { $0.rawTransactionId == pendingTx.rawTransactionId}) else {
|
||||
XCTFail("sent pending transaction not found after rewind")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertFalse(np.isMined)
|
||||
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
||||
notificationHandler.transactionsFound = { txs in
|
||||
XCTAssertEqual(txs.count, 1)
|
||||
guard let t = txs.first else {
|
||||
XCTFail("should have found sent transaction but didn't")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(t.rawTransactionId, pendingTx.rawTransactionId,"should have mined sent transaction but didn't")
|
||||
}
|
||||
notificationHandler.synchronizerMinedTransaction = { tx in
|
||||
XCTFail("We shouldn't find any mined transactions at this point but found \(tx)")
|
||||
}
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
confirmExpectation.fulfill()
|
||||
}, error: { e in
|
||||
self.handleError(e)
|
||||
})
|
||||
|
||||
wait(for: [confirmExpectation], timeout: 10)
|
||||
|
||||
let confirmedPending = try coordinator.synchronizer.allPendingTransactions().first(where: { $0.rawTransactionId == pendingTx.rawTransactionId})
|
||||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0)
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
import GRPC
|
||||
import NIO
|
||||
import SwiftProtobuf
|
||||
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
/// Usage: instantiate DarksideStreamerClient, then call methods of this protocol to make API calls.
|
||||
internal protocol DarksideStreamerClientProtocol: GRPCClient {
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
import ZcashLightClientKit
|
||||
import os
|
||||
|
||||
class SampleLogger: ZcashLightClientKit.Logger {
|
||||
enum LogLevel: Int {
|
||||
case debug
|
||||
|
@ -18,44 +19,54 @@ class SampleLogger: ZcashLightClientKit.Logger {
|
|||
case info
|
||||
}
|
||||
|
||||
enum LoggerType {
|
||||
case osLog
|
||||
case printerLog
|
||||
}
|
||||
|
||||
var level: LogLevel
|
||||
init(logLevel: LogLevel) {
|
||||
var loggerType: LoggerType
|
||||
|
||||
init(logLevel: LogLevel, type: LoggerType = .osLog) {
|
||||
self.level = logLevel
|
||||
self.loggerType = type
|
||||
}
|
||||
|
||||
private static let subsystem = Bundle.main.bundleIdentifier!
|
||||
static let oslog = OSLog(subsystem: subsystem, category: "test-logs")
|
||||
static let oslog = OSLog(subsystem: subsystem, category: "logs")
|
||||
|
||||
func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func debug(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue == LogLevel.debug.rawValue else { return }
|
||||
log(level: "DEBUG 🐞", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func error(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.error.rawValue else { return }
|
||||
log(level: "ERROR 💥", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func warn(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func warn(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.warning.rawValue else { return }
|
||||
log(level: "WARNING ⚠️", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func event(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func event(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.event.rawValue else { return }
|
||||
log(level: "EVENT ⏱", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
func info(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
guard level.rawValue <= LogLevel.info.rawValue else { return }
|
||||
log(level: "INFO ℹ️", message: message, file: file, function: function, line: line)
|
||||
}
|
||||
|
||||
private func log(level: String, message: String, file: String, function: String, line: Int) {
|
||||
let fileName = file as NSString
|
||||
|
||||
os_log("[%@] %@ - %@ - Line: %d -> %@", log: Self.oslog, type: .default, level, fileName.lastPathComponent, function, line, message)
|
||||
private func log(level: String, message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
||||
let fileName = (String(describing: file) as NSString).lastPathComponent
|
||||
switch loggerType {
|
||||
case .printerLog:
|
||||
print("[\(level)] \(fileName) - \(function) - line: \(line) -> \(message)")
|
||||
default:
|
||||
os_log("[%{public}@] %{public}@ - %{public}@ - Line: %{public}d -> %{public}@", level, fileName, String(describing: function), line, message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
# 0.10.0
|
||||
* [critical] Fix #255 #261 outgoing no-change transactions not reported as mined
|
||||
* [NEW] Rewind API. Allow Wallet developers to rewind synchronizer and (eventually) rescan
|
||||
* [NEW] Rust Welding 0.0.6 - using rust crates 0.5 and Data Access API
|
||||
* [NEW] updated Logger API to use StaticString on line and function as many logging libraries do
|
||||
* [FIX] Mac OS BIG SUR build fixed
|
||||
|
||||
|
||||
# 0.9.4
|
||||
* New: added viewing key derivation to Derivation Tool
|
||||
* Issue #252 - blockheight progress is latest height instead of upperbound of last scanned range
|
||||
|
|
342
rust/src/lib.rs
342
rust/src/lib.rs
|
@ -12,7 +12,7 @@ use zcash_client_backend::{
|
|||
chain::{scan_cached_blocks, validate_chain},
|
||||
error::Error,
|
||||
wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds, ANCHOR_OFFSET},
|
||||
WalletRead, WalletWrite,
|
||||
WalletRead,
|
||||
},
|
||||
encoding::{
|
||||
AddressCodec,
|
||||
|
@ -32,22 +32,18 @@ use zcash_client_backend::{
|
|||
use zcash_client_sqlite::{
|
||||
error::SqliteClientError,
|
||||
wallet::{
|
||||
rewind_to_height,
|
||||
put_received_transparent_utxo,
|
||||
init::{init_accounts_table, init_blocks_table, init_wallet_db,}
|
||||
},
|
||||
BlockDB, NoteId, WalletDB,
|
||||
|
||||
};
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{self,BlockHeight, BranchId, Parameters},
|
||||
note_encryption::Memo,
|
||||
transaction::{
|
||||
Transaction,
|
||||
components::{Amount, OutPoint},
|
||||
},
|
||||
|
||||
zip32::{ExtendedFullViewingKey},
|
||||
consensus::{BlockHeight, BranchId, Parameters},
|
||||
memo::{Memo, MemoBytes},
|
||||
transaction::{components::Amount, components::OutPoint, Transaction},
|
||||
zip32::ExtendedFullViewingKey,
|
||||
legacy::TransparentAddress,
|
||||
};
|
||||
|
||||
|
@ -62,7 +58,6 @@ use base58::ToBase58;
|
|||
use sha2::{Digest, Sha256};
|
||||
use secp256k1::key::SecretKey;
|
||||
|
||||
|
||||
fn unwrap_exc_or<T>(exc: Result<T, ()>, def: T) -> T {
|
||||
match exc {
|
||||
Ok(value) => value,
|
||||
|
@ -86,26 +81,36 @@ pub const NETWORK: MainNetwork = MAIN_NETWORK;
|
|||
#[cfg(not(feature = "mainnet"))]
|
||||
pub const NETWORK: TestNetwork = TEST_NETWORK;
|
||||
|
||||
|
||||
fn wallet_db<P: consensus::Parameters>(params: P,db_data: *const u8,
|
||||
db_data_len: usize) -> Result<WalletDB<P>, failure::Error> {
|
||||
|
||||
#[cfg(feature = "mainnet")]
|
||||
fn wallet_db(
|
||||
db_data: *const u8,
|
||||
db_data_len: usize,
|
||||
) -> Result<WalletDB<MainNetwork>, failure::Error> {
|
||||
let db_data = Path::new(OsStr::from_bytes(unsafe {
|
||||
slice::from_raw_parts(db_data, db_data_len)
|
||||
}));
|
||||
WalletDB::for_path(db_data, params)
|
||||
slice::from_raw_parts(db_data, db_data_len)
|
||||
}));
|
||||
WalletDB::for_path(db_data, NETWORK)
|
||||
.map_err(|e| format_err!("Error opening wallet database connection: {}", e))
|
||||
}
|
||||
|
||||
fn block_db(cache_db: *const u8,
|
||||
cache_db_len: usize) -> Result<BlockDB, failure::Error> {
|
||||
|
||||
#[cfg(not(feature = "mainnet"))]
|
||||
fn wallet_db(
|
||||
db_data: *const u8,
|
||||
db_data_len: usize,
|
||||
) -> Result<WalletDB<TestNetwork>, failure::Error> {
|
||||
let db_data = Path::new(OsStr::from_bytes(unsafe {
|
||||
slice::from_raw_parts(db_data, db_data_len)
|
||||
}));
|
||||
WalletDB::for_path(db_data, NETWORK)
|
||||
.map_err(|e| format_err!("Error opening wallet database connection: {}", e))
|
||||
}
|
||||
|
||||
fn block_db(cache_db: *const u8, cache_db_len: usize) -> Result<BlockDB, failure::Error> {
|
||||
let cache_db = Path::new(OsStr::from_bytes(unsafe {
|
||||
slice::from_raw_parts(cache_db, cache_db_len)
|
||||
}));
|
||||
BlockDB::for_path(cache_db)
|
||||
.map_err(|e| format_err!("Error opening block source database connection: {}", e))
|
||||
|
||||
.map_err(|e| format_err!("Error opening block source database connection: {}", e))
|
||||
}
|
||||
|
||||
/// Returns the length of the last error message to be logged.
|
||||
|
@ -133,11 +138,11 @@ pub extern "C" fn zcashlc_init_data_database(db_data: *const u8, db_data_len: us
|
|||
let db_data = Path::new(OsStr::from_bytes(unsafe {
|
||||
slice::from_raw_parts(db_data, db_data_len)
|
||||
}));
|
||||
|
||||
WalletDB::for_path(db_data, NETWORK)
|
||||
.map(|db| init_wallet_db(&db))
|
||||
.map(|_| 1)
|
||||
.map_err(|e| format_err!("Error while initializing data DB: {}", e))
|
||||
|
||||
WalletDB::for_path(db_data, NETWORK)
|
||||
.map(|db| init_wallet_db(&db))
|
||||
.map(|_| 1)
|
||||
.map_err(|e| format_err!("Error while initializing data DB: {}", e))
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
@ -158,7 +163,7 @@ pub extern "C" fn zcashlc_init_accounts_table(
|
|||
capacity_ret: *mut usize,
|
||||
) -> *mut *mut c_char {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let seed = unsafe { slice::from_raw_parts(seed, seed_len) };
|
||||
let accounts = if accounts >= 0 {
|
||||
accounts as u32
|
||||
|
@ -173,15 +178,17 @@ pub extern "C" fn zcashlc_init_accounts_table(
|
|||
|
||||
init_accounts_table(&db_data, &extfvks)
|
||||
.map(|_| {
|
||||
// Return the ExtendedSpendingKeys for the created accounts.
|
||||
// Return the ExtendedSpendingKeys for the created accounts.
|
||||
let mut v: Vec<_> = extsks
|
||||
.iter()
|
||||
.map(|extsk| {
|
||||
let encoded =
|
||||
encode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), extsk);
|
||||
CString::new(encoded).unwrap().into_raw()
|
||||
})
|
||||
.collect();
|
||||
.iter()
|
||||
.map(|extsk| {
|
||||
let encoded = encode_extended_spending_key(
|
||||
NETWORK.hrp_sapling_extended_spending_key(),
|
||||
extsk,
|
||||
);
|
||||
CString::new(encoded).unwrap().into_raw()
|
||||
})
|
||||
.collect();
|
||||
assert!(v.len() == accounts as usize);
|
||||
unsafe { *capacity_ret.as_mut().unwrap() = v.capacity() };
|
||||
let p = v.as_mut_ptr();
|
||||
|
@ -189,7 +196,6 @@ pub extern "C" fn zcashlc_init_accounts_table(
|
|||
return p;
|
||||
})
|
||||
.map_err(|e| format_err!("Error while initializing accounts: {}", e))
|
||||
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
@ -204,22 +210,27 @@ pub extern "C" fn zcashlc_init_accounts_table_with_keys(
|
|||
extfvks_len: usize,
|
||||
) -> bool {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
let extfvks = unsafe { std::slice::from_raw_parts(extfvks, extfvks_len)
|
||||
.into_iter()
|
||||
.map(|s| CStr::from_ptr(*s).to_str().unwrap())
|
||||
.map( |vkstr|
|
||||
decode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &vkstr)
|
||||
let extfvks = unsafe {
|
||||
std::slice::from_raw_parts(extfvks, extfvks_len)
|
||||
.into_iter()
|
||||
.map(|s| CStr::from_ptr(*s).to_str().unwrap())
|
||||
.map(|vkstr| {
|
||||
decode_extended_full_viewing_key(
|
||||
NETWORK.hrp_sapling_extended_full_viewing_key(),
|
||||
&vkstr,
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
).collect::<Vec<_>>() };
|
||||
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
match init_accounts_table(&db_data, &extfvks) {
|
||||
Ok(()) => Ok(true),
|
||||
Err(e) => Err(format_err!("Error while initializing accounts: {}", e)),
|
||||
}
|
||||
|
||||
});
|
||||
unwrap_exc_or(res, false)
|
||||
}
|
||||
|
@ -252,8 +263,10 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
|
|||
let mut v: Vec<_> = extsks
|
||||
.iter()
|
||||
.map(|extsk| {
|
||||
let encoded =
|
||||
encode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), extsk);
|
||||
let encoded = encode_extended_spending_key(
|
||||
NETWORK.hrp_sapling_extended_spending_key(),
|
||||
extsk,
|
||||
);
|
||||
CString::new(encoded).unwrap().into_raw()
|
||||
})
|
||||
.collect();
|
||||
|
@ -286,15 +299,19 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys(
|
|||
};
|
||||
|
||||
let extsks: Vec<_> = (0..accounts)
|
||||
.map(|account| ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), account)))
|
||||
.map(|account| {
|
||||
ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), account))
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Return the ExtendedSpendingKeys for the created accounts.
|
||||
let mut v: Vec<_> = extsks
|
||||
.iter()
|
||||
.map(|extsk| {
|
||||
let encoded =
|
||||
encode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), extsk);
|
||||
let encoded = encode_extended_full_viewing_key(
|
||||
NETWORK.hrp_sapling_extended_full_viewing_key(),
|
||||
extsk,
|
||||
);
|
||||
CString::new(encoded).unwrap().into_raw()
|
||||
})
|
||||
.collect();
|
||||
|
@ -306,7 +323,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys(
|
|||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
/// derives a shielded address from the given seed.
|
||||
/// derives a shielded address from the given seed.
|
||||
/// call zcashlc_string_free with the returned pointer when done using it
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
|
||||
|
@ -321,18 +338,14 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
|
|||
} else {
|
||||
return Err(format_err!("accounts argument must be greater than zero"));
|
||||
};
|
||||
let address_str = derive_shielded_address_from_seed(&NETWORK, &seed, account_index);
|
||||
Ok(CString::new(address_str).unwrap().into_raw())
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
||||
fn derive_shielded_address_from_seed<P: Parameters>(params: &P, seed: &[u8], account_index: u32) -> String {
|
||||
let address = spending_key(&seed, NETWORK.coin_type(), account_index)
|
||||
let address = spending_key(&seed, NETWORK.coin_type(), account_index)
|
||||
.default_address()
|
||||
.unwrap()
|
||||
.1;
|
||||
encode_payment_address(params.hrp_sapling_payment_address(), &address)
|
||||
let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address);
|
||||
Ok(CString::new(address_str).unwrap().into_raw())
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
||||
// fn derive_shielded_address_from_spending_k<P: Parameters>(params: &P, extsk: &ExtendedSpendingKey) -> String {
|
||||
|
@ -346,7 +359,6 @@ fn derive_shielded_address_from_seed<P: Parameters>(params: &P, seed: &[u8], acc
|
|||
pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key(
|
||||
extfvk: *const c_char,
|
||||
) -> *mut c_char {
|
||||
|
||||
let res = catch_panic(|| {
|
||||
let extfvk_string = CStr::from_ptr(extfvk).to_str()?;
|
||||
let extfvk = match decode_extended_full_viewing_key(
|
||||
|
@ -371,7 +383,7 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key(
|
|||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
||||
/// derives a shielded address from the given extended full viewing key.
|
||||
/// derives a shielded address from the given extended full viewing key.
|
||||
/// call zcashlc_string_free with the returned pointer when done using it
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key(
|
||||
|
@ -379,20 +391,26 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key(
|
|||
) -> *mut c_char {
|
||||
let res = catch_panic(|| {
|
||||
let extsk = CStr::from_ptr(extsk).to_str()?;
|
||||
let extfvk = match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk) {
|
||||
let extfvk = match decode_extended_spending_key(
|
||||
NETWORK.hrp_sapling_extended_spending_key(),
|
||||
&extsk,
|
||||
) {
|
||||
Ok(Some(extsk)) => ExtendedFullViewingKey::from(&extsk),
|
||||
Ok(None) => {
|
||||
return Err(format_err!("Deriving viewing key from spending key returned no results. Encoding was valid but type was incorrect."));
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format_err!(
|
||||
"Error while deriving viewing key from spending key: {}",
|
||||
e
|
||||
));
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let encoded = encode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &extfvk);
|
||||
let encoded = encode_extended_full_viewing_key(
|
||||
NETWORK.hrp_sapling_extended_full_viewing_key(),
|
||||
&extfvk,
|
||||
);
|
||||
|
||||
Ok(CString::new(encoded).unwrap().into_raw())
|
||||
});
|
||||
|
@ -413,7 +431,7 @@ pub extern "C" fn zcashlc_init_blocks_table(
|
|||
sapling_tree_hex: *const c_char,
|
||||
) -> i32 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let hash = {
|
||||
let mut hash = hex::decode(unsafe { CStr::from_ptr(hash_hex) }.to_str()?).unwrap();
|
||||
hash.reverse();
|
||||
|
@ -422,7 +440,13 @@ pub extern "C" fn zcashlc_init_blocks_table(
|
|||
let sapling_tree =
|
||||
hex::decode(unsafe { CStr::from_ptr(sapling_tree_hex) }.to_str()?).unwrap();
|
||||
|
||||
match init_blocks_table(&db_data, BlockHeight::from_u32(height as u32), hash,time, &sapling_tree) {
|
||||
match init_blocks_table(
|
||||
&db_data,
|
||||
BlockHeight::from_u32(height as u32),
|
||||
hash,
|
||||
time,
|
||||
&sapling_tree,
|
||||
) {
|
||||
Ok(()) => Ok(1),
|
||||
Err(e) => Err(format_err!("Error while initializing blocks table: {}", e)),
|
||||
}
|
||||
|
@ -440,7 +464,7 @@ pub extern "C" fn zcashlc_get_address(
|
|||
account: i32,
|
||||
) -> *mut c_char {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let account = if account >= 0 {
|
||||
account as u32
|
||||
} else {
|
||||
|
@ -454,7 +478,7 @@ pub extern "C" fn zcashlc_get_address(
|
|||
let addr_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &addr);
|
||||
let c_str_addr = CString::new(addr_str).unwrap();
|
||||
Ok(c_str_addr.into_raw())
|
||||
},
|
||||
}
|
||||
Ok(None) => Err(format_err!(
|
||||
"No payment address was available for account {:?}",
|
||||
account
|
||||
|
@ -497,7 +521,7 @@ pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_
|
|||
});
|
||||
unwrap_exc_or(res, false)
|
||||
}
|
||||
|
||||
/// returns whether the given viewing key is valid or not
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> bool {
|
||||
let res = catch_panic(|| {
|
||||
|
@ -527,34 +551,25 @@ fn is_valid_transparent_address(address: &str) -> bool {
|
|||
#[no_mangle]
|
||||
pub extern "C" fn zcashlc_get_balance(db_data: *const u8, db_data_len: usize, account: i32) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
let account = if account >= 0 {
|
||||
account as u32
|
||||
if account >= 0 {
|
||||
let (_, max_height) = (&db_data)
|
||||
.block_height_extrema()
|
||||
.map_err(|e| format_err!("Error while fetching max block height: {}", e))
|
||||
.and_then(|opt| {
|
||||
opt.ok_or(format_err!(
|
||||
"No blockchain information available; scan required."
|
||||
))
|
||||
})?;
|
||||
|
||||
(&db_data)
|
||||
.get_balance_at(AccountId(account as u32), max_height)
|
||||
.map(|b| b.into())
|
||||
.map_err(|e| format_err!("Error while fetching balance: {}", e))
|
||||
} else {
|
||||
return Err(format_err!("account argument must be positive"));
|
||||
};
|
||||
let account = AccountId(account);
|
||||
|
||||
// match db_data.get_balance(account) {
|
||||
// Ok(balance) => Ok(balance.into()),
|
||||
// Err(e) => Err(format_err!("Error while fetching balance: {}", e)),
|
||||
// }
|
||||
|
||||
(&db_data)
|
||||
.get_target_and_anchor_heights()
|
||||
.map_err(|e| format_err!("Error while fetching anchor height: {}", e))
|
||||
.and_then(|opt_anchor| {
|
||||
opt_anchor
|
||||
.map(|(h, _)| h)
|
||||
.ok_or(format_err!("height not available; scan required."))
|
||||
})
|
||||
.and_then(|height| {
|
||||
(&db_data)
|
||||
.get_balance_at(account, height)
|
||||
.map_err(|e| format_err!("Error while fetching verified balance: {}", e))
|
||||
})
|
||||
.map(|amount| amount.into())
|
||||
Err(format_err!("account argument must be positive"))
|
||||
}
|
||||
});
|
||||
unwrap_exc_or(res, -1)
|
||||
}
|
||||
|
@ -568,27 +583,25 @@ pub extern "C" fn zcashlc_get_verified_balance(
|
|||
account: i32,
|
||||
) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let account = if account >= 0 {
|
||||
account as u32
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
if account >= 0 {
|
||||
(&db_data)
|
||||
.get_target_and_anchor_heights()
|
||||
.map_err(|e| format_err!("Error while fetching anchor height: {}", e))
|
||||
.and_then(|opt_anchor| {
|
||||
opt_anchor
|
||||
.map(|(_, a)| a)
|
||||
.ok_or(format_err!("Anchor height not available; scan required."))
|
||||
})
|
||||
.and_then(|anchor| {
|
||||
(&db_data)
|
||||
.get_balance_at(AccountId(account as u32), anchor)
|
||||
.map_err(|e| format_err!("Error while fetching verified balance: {}", e))
|
||||
})
|
||||
.map(|amount| amount.into())
|
||||
} else {
|
||||
return Err(format_err!("account argument must be positive"));
|
||||
};
|
||||
let account = AccountId(account);
|
||||
(&db_data)
|
||||
.get_target_and_anchor_heights()
|
||||
.map_err(|e| format_err!("Error while fetching anchor height: {}", e))
|
||||
.and_then(|opt_anchor| {
|
||||
opt_anchor
|
||||
.map(|(_, a)| a)
|
||||
.ok_or(format_err!("Anchor height not available; scan required."))
|
||||
})
|
||||
.and_then(|anchor| {
|
||||
(&db_data)
|
||||
.get_balance_at(account, anchor)
|
||||
.map_err(|e| format_err!("Error while fetching verified balance: {}", e))
|
||||
})
|
||||
.map(|amount| amount.into())
|
||||
Err(format_err!("account argument must be positive"))
|
||||
}
|
||||
});
|
||||
unwrap_exc_or(res, -1)
|
||||
}
|
||||
|
@ -602,7 +615,7 @@ pub extern "C" fn zcashlc_get_verified_transparent_balance(
|
|||
address: *const c_char,
|
||||
) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let addr = unsafe { CStr::from_ptr(address).to_str()? };
|
||||
let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap();
|
||||
let amount = (&db_data)
|
||||
|
@ -636,7 +649,7 @@ pub extern "C" fn zcashlc_get_total_transparent_balance(
|
|||
address: *const c_char,
|
||||
) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let addr = unsafe { CStr::from_ptr(address).to_str()? };
|
||||
let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap();
|
||||
let amount = (&db_data)
|
||||
|
@ -661,6 +674,7 @@ pub extern "C" fn zcashlc_get_total_transparent_balance(
|
|||
unwrap_exc_or(res, -1)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the memo for a received note, if it is known and a valid UTF-8 string.
|
||||
///
|
||||
/// The note is identified by its row index in the `received_notes` table within the data
|
||||
|
@ -674,12 +688,17 @@ pub extern "C" fn zcashlc_get_received_memo_as_utf8(
|
|||
id_note: i64,
|
||||
) -> *mut c_char {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
let memo = match (&db_data).get_memo_as_utf8(NoteId::ReceivedNoteId(id_note)) {
|
||||
Ok(memo) => memo.unwrap_or_default(),
|
||||
Err(e) => return Err(format_err!("Error while fetching memo: {}", e)),
|
||||
};
|
||||
let memo = (&db_data).get_memo(NoteId::ReceivedNoteId(id_note))
|
||||
.map_err(|e| format_err!("An error occurred retrieving the memo, {}", e))
|
||||
.and_then(|memo| {
|
||||
match memo {
|
||||
Memo::Empty => Ok("".to_string()),
|
||||
Memo::Text(memo) => Ok(memo.into()),
|
||||
_ => Err(format_err!("This memo does not contain UTF-8 text")),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(CString::new(memo).unwrap().into_raw())
|
||||
});
|
||||
|
@ -699,13 +718,18 @@ pub extern "C" fn zcashlc_get_sent_memo_as_utf8(
|
|||
id_note: i64,
|
||||
) -> *mut c_char {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
|
||||
let memo = (&db_data)
|
||||
.get_memo_as_utf8(NoteId::SentNoteId(id_note))
|
||||
.map(|memo| memo.unwrap_or_default())
|
||||
.map_err(|e| format_err!("Error while fetching memo: {}", e))?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
let memo = (&db_data).get_memo(NoteId::SentNoteId(id_note))
|
||||
.map_err(|e| format_err!("An error occurred retrieving the memo, {}", e))
|
||||
.and_then(|memo| {
|
||||
match memo {
|
||||
Memo::Empty => Ok("".to_string()),
|
||||
Memo::Text(memo) => Ok(memo.into()),
|
||||
_ => Err(format_err!("This memo does not contain UTF-8 text")),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(CString::new(memo).unwrap().into_raw())
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
|
@ -736,12 +760,12 @@ pub extern "C" fn zcashlc_validate_combined_chain(
|
|||
) -> i32 {
|
||||
let res = catch_panic(|| {
|
||||
let block_db = block_db(db_cache, db_cache_len)?;
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
let validate_from = (&db_data)
|
||||
.get_max_height_hash()
|
||||
.map_err(|e| format_err!("Error while validating chain: {}", e))?;
|
||||
|
||||
|
||||
let val_res = validate_chain(&NETWORK, &block_db, validate_from);
|
||||
|
||||
if let Err(e) = val_res {
|
||||
|
@ -771,18 +795,17 @@ pub extern "C" fn zcashlc_rewind_to_height(
|
|||
height: i32,
|
||||
) -> i32 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
|
||||
// let mut update_ops = (&db_data)
|
||||
// .get_update_ops()
|
||||
// .map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
|
||||
|
||||
let mut update_ops = (&db_data)
|
||||
.get_update_ops()
|
||||
.map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
|
||||
|
||||
let height = BlockHeight::try_from(height)?;
|
||||
(&mut update_ops)
|
||||
.transactionally(|ops| ops.rewind_to_height(height))
|
||||
rewind_to_height(&db_data, height)
|
||||
.map(|_| 1)
|
||||
.map_err(|e| format_err!("Error while rewinding data DB to height {}: {}", height, e))
|
||||
|
||||
});
|
||||
unwrap_exc_or_null(res)
|
||||
}
|
||||
|
@ -810,8 +833,8 @@ pub extern "C" fn zcashlc_scan_blocks(
|
|||
) -> i32 {
|
||||
let res = catch_panic(|| {
|
||||
let block_db = block_db(db_cache, db_cache_len)?;
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let mut db_data = db_data.get_update_ops()?;
|
||||
let db_read = wallet_db(db_data, db_data_len)?;
|
||||
let mut db_data = db_read.get_update_ops()?;
|
||||
|
||||
match scan_cached_blocks(&NETWORK, &block_db, &mut db_data, None) {
|
||||
Ok(()) => Ok(1),
|
||||
|
@ -835,7 +858,7 @@ pub extern "C" fn zcashlc_put_utxo(
|
|||
height: i32,
|
||||
) -> bool {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let mut db_data = db_data.get_update_ops()?;
|
||||
|
||||
let addr = unsafe {CStr::from_ptr(address_str).to_str()? };
|
||||
|
@ -871,8 +894,8 @@ pub extern "C" fn zcashlc_decrypt_and_store_transaction(
|
|||
tx_len: usize,
|
||||
) -> i32 {
|
||||
let res = catch_panic(|| {
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let mut db_data = db_data.get_update_ops()?;
|
||||
let db_read = wallet_db(db_data, db_data_len)?;
|
||||
let mut db_data = db_read.get_update_ops()?;
|
||||
let tx_bytes = unsafe { slice::from_raw_parts(tx, tx_len) };
|
||||
let tx = Transaction::read(&tx_bytes[..])?;
|
||||
|
||||
|
@ -907,9 +930,8 @@ pub extern "C" fn zcashlc_create_to_address(
|
|||
output_params_len: usize,
|
||||
) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let mut db_data = db_data.get_update_ops()?;
|
||||
let db_read = wallet_db(db_data, db_data_len)?;
|
||||
let mut db_data = db_read.get_update_ops()?;
|
||||
let account = if account >= 0 {
|
||||
account as u32
|
||||
} else {
|
||||
|
@ -936,17 +958,17 @@ pub extern "C" fn zcashlc_create_to_address(
|
|||
Ok(Some(extsk)) => extsk,
|
||||
Ok(None) => {
|
||||
return Err(format_err!("ExtendedSpendingKey is for the wrong network"));
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let to = match RecipientAddress::decode(&NETWORK, &to) {
|
||||
Some(to) => to,
|
||||
None => {
|
||||
return Err(format_err!("PaymentAddress is for the wrong network"));
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
|
||||
|
@ -961,7 +983,7 @@ pub extern "C" fn zcashlc_create_to_address(
|
|||
&extsk,
|
||||
&to,
|
||||
value,
|
||||
Some(memo),
|
||||
Some(MemoBytes::from(memo)),
|
||||
OvkPolicy::Sender,
|
||||
)
|
||||
.map_err(|e| format_err!("Error while sending funds: {}", e))
|
||||
|
@ -1046,7 +1068,6 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
|
|||
account: i32,
|
||||
index: i32,
|
||||
) -> *mut c_char {
|
||||
|
||||
let res = catch_panic(|| {
|
||||
let seed = slice::from_raw_parts(seed, seed_len);
|
||||
let account = if account >= 0 {
|
||||
|
@ -1134,7 +1155,7 @@ pub extern "C" fn zcashlc_shield_funds(
|
|||
) -> i64 {
|
||||
let res = catch_panic(|| {
|
||||
|
||||
let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
|
||||
let db_data = wallet_db(db_data, db_data_len)?;
|
||||
let mut update_ops = (&db_data)
|
||||
.get_update_ops()
|
||||
.map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
|
||||
|
@ -1168,12 +1189,9 @@ pub extern "C" fn zcashlc_shield_funds(
|
|||
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
|
||||
},
|
||||
};
|
||||
let memo = match Memo::from_str(&memo) {
|
||||
Ok(memo) => memo,
|
||||
Err(_) => {
|
||||
return Err(format_err!("Invalid memo input"));
|
||||
}
|
||||
};
|
||||
|
||||
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
|
||||
let memo_bytes = MemoBytes::from(memo);
|
||||
// shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params)
|
||||
shield_funds(&mut update_ops,
|
||||
&NETWORK,
|
||||
|
@ -1181,7 +1199,7 @@ pub extern "C" fn zcashlc_shield_funds(
|
|||
AccountId(account),
|
||||
&sk,
|
||||
&extsk,
|
||||
&memo,
|
||||
&memo_bytes,
|
||||
ANCHOR_OFFSET)
|
||||
.map_err(|e| format_err!("Error while shielding transaction: {}", e))
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue