[WIP] data access api compliance

This commit is contained in:
Francisco Gindre 2021-02-17 20:02:25 -03:00
parent 2d76c96b42
commit 1affc50726
13 changed files with 407 additions and 425 deletions

142
Cargo.lock generated
View File

@ -98,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"miniz_oxide", "miniz_oxide",
"object", "object",
@ -131,9 +131,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]] [[package]]
name = "bech32" name = "bech32"
version = "0.7.2" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdcf67bb7ba7797a081cd19009948ab533af7c355d5caf1d08c777582d351e9c" checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1"
[[package]] [[package]]
name = "bellman" name = "bellman"
@ -307,15 +307,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.41" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -363,7 +357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if 1.0.0", "cfg-if",
"lazy_static", "lazy_static",
] ]
@ -546,7 +540,7 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"wasi 0.9.0+wasi-snapshot-preview1", "wasi 0.9.0+wasi-snapshot-preview1",
] ]
@ -557,7 +551,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"wasi 0.10.2+wasi-snapshot-preview1", "wasi 0.10.2+wasi-snapshot-preview1",
] ]
@ -601,13 +595,24 @@ dependencies = [
[[package]] [[package]]
name = "hdwallet" name = "hdwallet"
version = "0.2.5" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/nuttycom/hdwallet?rev=72f1f7a56c114eed484cefd6d402b7ef28158712#72f1f7a56c114eed484cefd6d402b7ef28158712"
checksum = "35b15cc3c181a2aace485d56c784568a4ae6e34322287a2499549d4cda7af3e1"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"rand 0.7.3", "rand_core 0.6.2",
"ring", "ring",
"secp256k1 0.17.2", "secp256k1",
]
[[package]]
name = "hdwallet"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2033326faddc94885c26775db24683819bf3ae9461e016c45df18b910bdeedd7"
dependencies = [
"lazy_static",
"rand_core 0.6.2",
"ring",
"secp256k1",
] ]
[[package]] [[package]]
@ -671,22 +676,22 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "lexical-core" name = "lexical-core"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bitflags", "bitflags",
"cfg-if 0.1.10", "cfg-if",
"ryu", "ryu",
"static_assertions", "static_assertions",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.85" version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
@ -708,10 +713,11 @@ dependencies = [
"cbindgen", "cbindgen",
"failure", "failure",
"ffi_helpers", "ffi_helpers",
"hdwallet", "funty",
"hdwallet 0.3.0",
"hex", "hex",
"ripemd160", "ripemd160",
"secp256k1 0.19.0", "secp256k1",
"sha2 0.9.3", "sha2 0.9.3",
"time", "time",
"zcash_client_backend", "zcash_client_backend",
@ -726,7 +732,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
] ]
[[package]] [[package]]
@ -792,6 +798,12 @@ version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "once_cell"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
version = "0.2.3" version = "0.2.3"
@ -849,24 +861,24 @@ dependencies = [
[[package]] [[package]]
name = "protobuf" name = "protobuf"
version = "2.20.0" version = "2.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86473d5f16580f10b131a0bf0afb68f8e029d1835d33a00f37281b05694e5312" checksum = "73f72884896d22e0da0e5b266cb9a780b791f6c3b2f5beab6368d6cd4f0dbb86"
[[package]] [[package]]
name = "protobuf-codegen" name = "protobuf-codegen"
version = "2.20.0" version = "2.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8b6ba4581fcd9c3ce3576f25e528467b0d3516e332884c0da6f2084fe59045f" checksum = "e8217a1652dbc91d19c509c558234145faed729191a966896414e5889f62d543"
dependencies = [ dependencies = [
"protobuf", "protobuf",
] ]
[[package]] [[package]]
name = "protobuf-codegen-pure" name = "protobuf-codegen-pure"
version = "2.20.0" version = "2.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cc5a64733bf127b466ca734a39ad1b123ac37bfe96c5a340fa6f5393dfd964" checksum = "1f239d71417bdc5f8d83c07aeb265f911346e5540a1a6c4285f9c3d1966ed6e3"
dependencies = [ dependencies = [
"protobuf", "protobuf",
"protobuf-codegen", "protobuf-codegen",
@ -874,9 +886,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.8" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -908,7 +920,7 @@ checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha 0.3.0", "rand_chacha 0.3.0",
"rand_core 0.6.1", "rand_core 0.6.2",
"rand_hc 0.3.0", "rand_hc 0.3.0",
] ]
@ -929,7 +941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core 0.6.1", "rand_core 0.6.2",
] ]
[[package]] [[package]]
@ -943,9 +955,9 @@ dependencies = [
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.6.1" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [ dependencies = [
"getrandom 0.2.2", "getrandom 0.2.2",
] ]
@ -965,7 +977,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [ dependencies = [
"rand_core 0.6.1", "rand_core 0.6.2",
] ]
[[package]] [[package]]
@ -976,9 +988,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.4" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
@ -1005,13 +1017,13 @@ dependencies = [
[[package]] [[package]]
name = "ring" name = "ring"
version = "0.16.12" version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [ dependencies = [
"cc", "cc",
"lazy_static",
"libc", "libc",
"once_cell",
"spin", "spin",
"untrusted", "untrusted",
"web-sys", "web-sys",
@ -1078,31 +1090,13 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "secp256k1"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
dependencies = [
"secp256k1-sys 0.1.2",
]
[[package]] [[package]]
name = "secp256k1" name = "secp256k1"
version = "0.19.0" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb" checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb"
dependencies = [ dependencies = [
"secp256k1-sys 0.3.0", "secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220"
dependencies = [
"cc",
] ]
[[package]] [[package]]
@ -1151,9 +1145,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.61" version = "1.0.62"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1185,7 +1179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
dependencies = [ dependencies = [
"block-buffer 0.9.0", "block-buffer 0.9.0",
"cfg-if 1.0.0", "cfg-if",
"cpuid-bool", "cpuid-bool",
"digest 0.9.0", "digest 0.9.0",
"opaque-debug 0.3.0", "opaque-debug 0.3.0",
@ -1205,9 +1199,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "standback" name = "standback"
version = "0.2.14" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66a8cff4fa24853fdf6b51f75c6d7f8206d7c75cab4e467bcd7f25c2b1febe0" checksum = "a2beb4d1860a61f571530b3f855a1b538d0200f7871c63331ecd6f17b1f014f8"
dependencies = [ dependencies = [
"version_check", "version_check",
] ]
@ -1308,10 +1302,10 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"rand 0.8.3", "rand 0.8.3",
"redox_syscall 0.2.4", "redox_syscall 0.2.5",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi",
] ]
@ -1438,7 +1432,7 @@ version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
] ]
@ -1534,6 +1528,7 @@ dependencies = [
"bs58", "bs58",
"ff", "ff",
"group", "group",
"hdwallet 0.2.5",
"hex", "hex",
"jubjub", "jubjub",
"nom", "nom",
@ -1541,6 +1536,9 @@ dependencies = [
"protobuf", "protobuf",
"protobuf-codegen-pure", "protobuf-codegen-pure",
"rand_core 0.5.1", "rand_core 0.5.1",
"ripemd160",
"secp256k1",
"sha2 0.9.3",
"subtle", "subtle",
"time", "time",
"zcash_primitives", "zcash_primitives",
@ -1585,7 +1583,7 @@ dependencies = [
"rand 0.7.3", "rand 0.7.3",
"rand_core 0.5.1", "rand_core 0.5.1",
"ripemd160", "ripemd160",
"secp256k1 0.19.0", "secp256k1",
"sha2 0.9.3", "sha2 0.9.3",
"subtle", "subtle",
] ]

View File

@ -11,18 +11,19 @@ build = "rust/build.rs"
failure = "0.1" failure = "0.1"
ffi_helpers = "0.2" ffi_helpers = "0.2"
hex = "0.4" hex = "0.4"
zcash_client_backend = "0.4" zcash_client_backend = { version = "0.4", features = ["transparent-inputs"] }
zcash_client_sqlite = "0.2.1" zcash_client_sqlite = { version = "0.2.1", features = ["transparent-inputs"] }
zcash_primitives = { version = "0.4", features = ["transparent-inputs"] } zcash_primitives = { version = "0.4", features = ["transparent-inputs"] }
#### Temporary additions: #################################### #### Temporary additions: ####################################
base58 = "0.1.0" base58 = "0.1.0"
sha2 = "0.9" sha2 = "0.9"
bs58 = { version = "0.3", features = ["check"] } bs58 = { version = "0.3", features = ["check"] }
hdwallet = "0.2.2" hdwallet = "0.3.0"
ripemd160 = "0.9" ripemd160 = "0.9"
secp256k1 = "0.19" secp256k1 = "0.19"
time = "0.2" time = "0.2"
funty = "=1.1.0"
############################################################## ##############################################################
@ -43,10 +44,10 @@ crate-type = ["staticlib"]
lto = true lto = true
[patch.crates-io] [patch.crates-io]
#zcash_client_backend = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" } #zcash_client_backend = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa" }
#zcash_client_sqlite = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" } #zcash_client_sqlite = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa" }
#zcash_primitives = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" } #zcash_primitives = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa" }
#zcash_proofs = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" } #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_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_client_sqlite = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_client_sqlite" }
@ -54,4 +55,5 @@ zcash_primitives = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_primi
zcash_proofs = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_proofs" } zcash_proofs = { path = "/Users/pacu/Repos/ECC/pacu-librustzcash/zcash_proofs" }
[features] [features]
mainnet = ["zcash_client_sqlite/mainnet"] 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"]

View File

@ -10,11 +10,11 @@ import Foundation
import ZcashLightClientKit import ZcashLightClientKit
import MnemonicSwift import MnemonicSwift
struct DemoAppConfig { struct DemoAppConfig {
static var host = ZcashSDK.isMainnet ? "localhost" : "lightwalletd.testnet.electriccoin.co" static var host = ZcashSDK.isMainnet ? "lightwalletd.electriccoin.co" : "lightwalletd.testnet.electriccoin.co"
static var port: Int = 9067 static var port: Int = 9067
static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 663174 : 620_000 static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 935000 : 620_000
static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet
static var seed = ZcashSDK.isMainnet ? try! Mnemonic.deterministicSeedBytes(from: "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread") : Array("testreferencealicetestreferencealice".utf8) static var seed = ZcashSDK.isMainnet ? try! Mnemonic.deterministicSeedBytes(from: "old wise letter cigar ready miracle settle crystal bag amateur dial index slot dune crisp ready chest advice camera always drive dentist sport smoke") : Array("testreferencealicetestreferencealice".utf8)
static var address: String { static var address: String {
"\(host):\(port)" "\(host):\(port)"
} }

View File

@ -123,7 +123,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
} }
} }
func balance(address: String, latestHeight: BlockHeight) throws -> UnshieldedBalance { func balance(address: String, latestHeight: BlockHeight) throws -> WalletBalance {
do { do {
let confirmed = try dbProvider.connection().scalar( let confirmed = try dbProvider.connection().scalar(
@ -142,7 +142,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
} }
} }
struct TransparentBalance: UnshieldedBalance { struct TransparentBalance: WalletBalance {
var confirmed: Int64 var confirmed: Int64
var unconfirmed: Int64 var unconfirmed: Int64
var address: String var address: String

View File

@ -7,16 +7,11 @@
import Foundation import Foundation
public protocol UnshieldedBalance {
var confirmed: Int64 { get set }
var unconfirmed: Int64 { get set }
}
protocol UnspentTransactionOutputRepository { protocol UnspentTransactionOutputRepository {
func getAll(address: String?) throws -> [UnspentTransactionOutputEntity] func getAll(address: String?) throws -> [UnspentTransactionOutputEntity]
func balance(address: String, latestHeight: BlockHeight) throws -> UnshieldedBalance func balance(address: String, latestHeight: BlockHeight) throws -> WalletBalance
func store(utxos: [UnspentTransactionOutputEntity]) throws func store(utxos: [UnspentTransactionOutputEntity]) throws

View File

@ -9,6 +9,34 @@
import Foundation import Foundation
class ZcashRustBackend: ZcashRustBackendWelding { class ZcashRustBackend: ZcashRustBackendWelding {
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool {
let dbData = dbData.osStr()
guard !address.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard zcashlc_put_utxo(dbData.0,
dbData.1,
[CChar](address.utf8CString),
txid,
UInt(txid.count),
Int32(index),
script,
UInt(script.count),
value,
Int32(height)) else {
if let error = lastError() {
throw error
}
return false
}
return true
}
static func lastError() -> RustWeldingError? { static func lastError() -> RustWeldingError? {
guard let message = getLastError() else { return nil } guard let message = getLastError() else { return nil }
@ -207,7 +235,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count)) != 0 return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count)) != 0
} }
static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32,to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let memoBytes = memo ?? "" let memoBytes = memo ?? ""
@ -215,7 +243,6 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData.1, dbData.1,
account, account,
[CChar](extsk.utf8CString), [CChar](extsk.utf8CString),
consensusBranchId,
[CChar](to.utf8CString), [CChar](to.utf8CString),
value, value,
[CChar](memoBytes.utf8CString), [CChar](memoBytes.utf8CString),
@ -227,17 +254,14 @@ class ZcashRustBackend: ZcashRustBackendWelding {
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 { static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let dbCache = dbCache.osStr()
let memoBytes = memo ?? "" let memoBytes = memo ?? ""
return zcashlc_shield_funds(dbData.0, return zcashlc_shield_funds(dbData.0,
dbData.1, dbData.1,
dbCache.0,
dbCache.1,
account, account,
tsk, [CChar](tsk.utf8CString),
extsk, [CChar](extsk.utf8CString),
memoBytes, [CChar](memoBytes.utf8CString),
spendParamsPath, spendParamsPath,
UInt(spendParamsPath.lengthOfBytes(using: .utf8)), UInt(spendParamsPath.lengthOfBytes(using: .utf8)),
outputParamsPath, outputParamsPath,
@ -329,9 +353,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return zAddr return zAddr
} }
static func deriveTransparentAddressFromSeed(seed: [UInt8]) throws -> String? { static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count)) else { guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else {
if let error = lastError() { if let error = lastError() {
throw error throw error
} }
@ -343,8 +367,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return tAddr return tAddr
} }
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8]) throws -> String? { static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count)) else { guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else {
if let error = lastError() { if let error = lastError() {
throw error throw error
} }

View File

@ -165,6 +165,18 @@ public protocol ZcashRustBackendWelding {
*/ */
static func scanBlocks(dbCache: URL, dbData: URL) -> Bool static func scanBlocks(dbCache: URL, dbData: URL) -> Bool
/**
puts a UTXO into the data db database
- Parameters:
- dbData: location of the data db file
- address: the address of the UTXO
- txid: the txid bytes for the UTXO
- index: the index of the UTXO
- value: the value of the UTXO
- height: the mined height for the UTXO
- Returns: true if the operation succeded or false otherwise
*/
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool
/** /**
Scans a transaction for any information that can be decrypted by the accounts in the Scans a transaction for any information that can be decrypted by the accounts in the
wallet, and saves it to the wallet. wallet, and saves it to the wallet.
@ -188,7 +200,7 @@ public protocol ZcashRustBackendWelding {
- spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located - spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located
- outputParamsPath: path escaped String for the filesystem locations where the output parameters are located - outputParamsPath: path escaped String for the filesystem locations where the output parameters are located
*/ */
static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64
/** /**
Creates a transaction to shield all found UTXOs in cache db. Creates a transaction to shield all found UTXOs in cache db.
@ -253,14 +265,14 @@ public protocol ZcashRustBackendWelding {
- Returns: an optional String containing the transparent address - Returns: an optional String containing the transparent address
- Throws: RustBackendError if fatal error occurs - Throws: RustBackendError if fatal error occurs
*/ */
static func deriveTransparentAddressFromSeed(seed: [UInt8]) throws -> String? static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String?
/** /**
Derives a transparent secret key from Seed Derives a transparent secret key from Seed
- Parameter seed: an array of bytes containing the seed - Parameter seed: an array of bytes containing the seed
- Returns: an optional String containing the transparent secret (private) key - Returns: an optional String containing the transparent secret (private) key
*/ */
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8]) throws -> String? static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String?
/** /**
Derives a transparent address from a secret key Derives a transparent address from a secret key

View File

@ -44,6 +44,10 @@ extension ShieldFundsError: LocalizedError {
} }
public protocol WalletBalance {
var confirmed: Int64 { get set }
var unconfirmed: Int64 { get set }
}
/** /**
Primary interface for interacting with the SDK. Defines the contract that specific Primary interface for interacting with the SDK. Defines the contract that specific
@ -170,6 +174,11 @@ public protocol Synchronizer {
*/ */
func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void)
/**
Gets the latests UTXOs for the given address from the specified height on
*/
func refreshUTXOs(address: String, from height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity],Error>) -> Void)
/** /**
gets the latest cached UTXOs for the given t-address for the given address gets the latest cached UTXOs for the given t-address for the given address
*/ */
@ -178,12 +187,13 @@ public protocol Synchronizer {
/** /**
gets the unshielded balance for the given address. gets the unshielded balance for the given address.
*/ */
func latestUnshieldedBalance(address: String, result: @escaping (Result<UnshieldedBalance,Error>) -> Void) func latestUnshieldedBalance(address: String, result: @escaping (Result<WalletBalance,Error>) -> Void)
/** /**
gets the last stored unshielded balance gets the last stored unshielded balance
*/ */
func getUnshieldedBalance(address: String) throws -> UnshieldedBalance func getTransparentBalance(address: String) throws -> WalletBalance
} }
/** /**

View File

@ -77,12 +77,12 @@ public protocol KeyDeriving {
// WIP probably shouldn't be used just yet. Why? // WIP probably shouldn't be used just yet. Why?
// - because we need the private key associated with this seed and this function doesn't return it. // - because we need the private key associated with this seed and this function doesn't return it.
// - the underlying implementation needs to be split out into a few lower-level calls // - the underlying implementation needs to be split out into a few lower-level calls
func deriveTransparentAddress(seed: [UInt8]) throws -> String func deriveTransparentAddress(seed: [UInt8], account: Int, index: Int) throws -> String
/** /**
Derives a SecretKey to spend transparent funds from the given seed Derives a SecretKey to spend transparent funds from the given seed
*/ */
func deriveTransparentPrivateKey(seed: [UInt8]) throws -> String func deriveTransparentPrivateKey(seed: [UInt8], account: Int, index: Int) throws -> String
/** /**
Derives a transparent address from the given transparent Secret Key Derives a transparent address from the given transparent Secret Key
@ -215,9 +215,9 @@ public class DerivationTool: KeyDeriving {
// WIP probably shouldn't be used just yet. Why? // WIP probably shouldn't be used just yet. Why?
// - because we need the private key associated with this seed and this function doesn't return it. // - because we need the private key associated with this seed and this function doesn't return it.
// - the underlying implementation needs to be split out into a few lower-level calls // - the underlying implementation needs to be split out into a few lower-level calls
public func deriveTransparentAddress(seed: [UInt8]) throws -> String { public func deriveTransparentAddress(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String {
do { do {
guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed) else { guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed, account: account, index: index) else {
throw KeyDerivationErrors.unableToDerive throw KeyDerivationErrors.unableToDerive
} }
return zaddr return zaddr
@ -237,9 +237,9 @@ public class DerivationTool: KeyDeriving {
- KeyDerivationErrors.derivationError with the underlying error when it fails - KeyDerivationErrors.derivationError with the underlying error when it fails
- KeyDerivationErrors.unableToDerive when there's an unknown error - KeyDerivationErrors.unableToDerive when there's an unknown error
*/ */
public func deriveTransparentPrivateKey(seed: [UInt8]) throws -> String { public func deriveTransparentPrivateKey(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String {
do { do {
guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed) else { guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed, account: account, index: index) else {
throw KeyDerivationErrors.unableToDerive throw KeyDerivationErrors.unableToDerive
} }
return sk return sk
@ -276,6 +276,12 @@ extension DerivationTool: KeyValidation {
} }
/**
Derives the transparent address from a WIF Private Key
- Throws:
- KeyDerivationErrors.derivationError with the underlying error when it fails
- KeyDerivationErrors.unableToDerive when there's an unknown error
*/
public func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String { public func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String {
do { do {
guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk) else { guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk) else {

View File

@ -84,12 +84,9 @@ class WalletTransactionEncoder: TransactionEncoder {
throw RustWeldingError.genericError(message: "could not convert \(scannedHeight)") throw RustWeldingError.genericError(message: "could not convert \(scannedHeight)")
} }
let consensusBranchId = try rustBackend.consensusBranchIdFor(height: latestHeight)
let txId = rustBackend.createToAddress(dbData: self.dataDbURL, let txId = rustBackend.createToAddress(dbData: self.dataDbURL,
account: Int32(accountIndex), account: Int32(accountIndex),
extsk: spendingKey, extsk: spendingKey,
consensusBranchId: consensusBranchId,
to: address, to: address,
value: Int64(zatoshi), value: Int64(zatoshi),
memo: memo, memo: memo,

View File

@ -495,7 +495,7 @@ public class SDKSynchronizer: Synchronizer {
/** /**
gets the unshielded balance for the given address. gets the unshielded balance for the given address.
*/ */
public func latestUnshieldedBalance(address: String, result: @escaping (Result<UnshieldedBalance,Error>) -> Void) { public func latestUnshieldedBalance(address: String, result: @escaping (Result<WalletBalance,Error>) -> Void) {
latestUTXOs(address: address, result: { [weak self] (r) in latestUTXOs(address: address, result: { [weak self] (r) in
guard let self = self else { return } guard let self = self else { return }
@ -515,7 +515,7 @@ public class SDKSynchronizer: Synchronizer {
/** /**
gets the last stored unshielded balance gets the last stored unshielded balance
*/ */
public func getUnshieldedBalance(address: String) throws -> UnshieldedBalance { public func getTransparentBalance(address: String) throws -> WalletBalance {
do { do {
let latestHeight = try self.latestDownloadedHeight() let latestHeight = try self.latestDownloadedHeight()
let cachedBalance = try utxoRepository.balance(address: address, latestHeight: latestHeight) let cachedBalance = try utxoRepository.balance(address: address, latestHeight: latestHeight)

View File

@ -82,14 +82,17 @@ char *zcashlc_derive_shielded_address_from_seed(const uint8_t *seed,
char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk); char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk);
/** /**
* Derives a transparent address from the given seed * Derives a transparent address from the given secret key enconded as a WIF string
*/ */
char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk); char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk);
/** /**
* Derives a transparent address from the given seed * Derives a transparent address from the given seed
*/ */
char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed, uintptr_t seed_len); char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t account,
int32_t index);
/** /**
* TEST TEST 123 TEST * TEST TEST 123 TEST
@ -97,7 +100,10 @@ char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed, uintptr_
* *
* Derives a transparent private key from seed * Derives a transparent private key from seed
*/ */
char *zcashlc_derive_transparent_private_key_from_seed(const uint8_t *seed, uintptr_t seed_len); char *zcashlc_derive_transparent_private_key_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t account,
int32_t index);
/** /**
* Copies the last error message into the provided allocated buffer. * Copies the last error message into the provided allocated buffer.
@ -138,6 +144,14 @@ char *zcashlc_get_received_memo_as_utf8(const uint8_t *db_data,
*/ */
char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_len, int64_t id_note); char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_len, int64_t id_note);
/**
* Returns the verified transparent balance for the address, which ignores utxos that have been
* received too recently and are not yet deemed spendable.
*/
int64_t zcashlc_get_total_transparent_balance(const uint8_t *db_data,
uintptr_t db_data_len,
const char *address);
/** /**
* Returns the verified balance for the account, which ignores notes that have been * Returns the verified balance for the account, which ignores notes that have been
* received too recently and are not yet deemed spendable. * received too recently and are not yet deemed spendable.
@ -146,6 +160,14 @@ int64_t zcashlc_get_verified_balance(const uint8_t *db_data,
uintptr_t db_data_len, uintptr_t db_data_len,
int32_t account); int32_t account);
/**
* Returns the verified transparent balance for the address, which ignores utxos that have been
* received too recently and are not yet deemed spendable.
*/
int64_t zcashlc_get_verified_transparent_balance(const uint8_t *db_data,
uintptr_t db_data_len,
const char *address);
/** /**
* Initialises the data database with the given number of accounts using the given seed. * Initialises the data database with the given number of accounts using the given seed.
* *
@ -208,6 +230,17 @@ bool zcashlc_is_valid_viewing_key(const char *key);
*/ */
int32_t zcashlc_last_error_length(void); int32_t zcashlc_last_error_length(void);
bool zcashlc_put_utxo(const uint8_t *db_data,
uintptr_t db_data_len,
const char *address_str,
const uint8_t *txid_bytes,
uintptr_t txid_bytes_len,
int32_t index,
const uint8_t *script_bytes,
uintptr_t script_bytes_len,
int64_t value,
int32_t height);
/** /**
* Rewinds the data database to the given height. * Rewinds the data database to the given height.
* *
@ -239,8 +272,6 @@ int32_t zcashlc_scan_blocks(const uint8_t *db_cache,
int64_t zcashlc_shield_funds(const uint8_t *db_data, int64_t zcashlc_shield_funds(const uint8_t *db_data,
uintptr_t db_data_len, uintptr_t db_data_len,
const uint8_t *db_cache,
uintptr_t db_cache_len,
int32_t account, int32_t account,
const char *tsk, const char *tsk,
const char *extsk, const char *extsk,

View File

@ -8,42 +8,47 @@ use std::slice;
use std::str::FromStr; use std::str::FromStr;
use zcash_client_backend::{ use zcash_client_backend::{
address::RecipientAddress, address::RecipientAddress,
wallet::AccountId,
data_api::{ data_api::{
chain::{scan_cached_blocks, validate_chain}, chain::{scan_cached_blocks, validate_chain},
error::Error, error::Error,
wallet::{create_spend_to_address, decrypt_and_store_transaction}, wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds, ANCHOR_OFFSET},
WalletRead, WalletWrite, WalletRead, WalletWrite,
}, },
encoding::{ encoding::{
decode_extended_full_viewing_key, decode_extended_spending_key, AddressCodec,
encode_extended_full_viewing_key, encode_extended_spending_key, encode_payment_address, decode_extended_full_viewing_key,
decode_extended_spending_key,
encode_extended_full_viewing_key,
encode_extended_spending_key,
encode_payment_address,
}, },
keys::spending_key, keys::{
wallet::OvkPolicy, derive_secret_key_from_seed,
derive_transparent_address_from_secret_key,
spending_key, Wif,
},
wallet::{AccountId, OvkPolicy, WalletTransparentOutput},
}; };
use zcash_client_sqlite::{ use zcash_client_sqlite::{
error::SqliteClientError, error::SqliteClientError,
wallet::{ wallet::{
init::{init_accounts_table, init_blocks_table, init_wallet_db} put_received_transparent_utxo,
init::{init_accounts_table, init_blocks_table, init_wallet_db,}
}, },
BlockDB, NoteId, WalletDB, BlockDB, NoteId, WalletDB,
chain::get_confirmed_utxos_for_address,
}; };
use zcash_primitives::{ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus::{self,BlockHeight, BranchId, Parameters}, consensus::{self,BlockHeight, BranchId, Parameters},
note_encryption::Memo, note_encryption::Memo,
transaction::components::{ transaction::{
amount::DEFAULT_FEE, Transaction,
Amount, components::{Amount, OutPoint},
OutPoint,
TxOut
}, },
legacy::Script,
transaction::builder::Builder,
transaction::Transaction,
zip32::{ExtendedFullViewingKey}, zip32::{ExtendedFullViewingKey},
legacy::TransparentAddress,
}; };
#[cfg(feature = "mainnet")] #[cfg(feature = "mainnet")]
@ -52,23 +57,10 @@ use zcash_primitives::consensus::{MainNetwork, MAIN_NETWORK};
use zcash_primitives::consensus::{TestNetwork, TEST_NETWORK}; use zcash_primitives::consensus::{TestNetwork, TEST_NETWORK};
use zcash_proofs::prover::LocalTxProver; use zcash_proofs::prover::LocalTxProver;
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
// /////////////////////////////////////////////////////////////////////////////////////////////////
// Temporary Imports
use base58::ToBase58; use base58::ToBase58;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
// use zcash_primitives::legacy::TransparentAddress; use secp256k1::key::SecretKey;
use hdwallet::{ExtendedPrivKey, KeyIndex};
use secp256k1::{
Secp256k1,
key::{PublicKey, SecretKey},
};
// use crate::extended_key::{key_index::KeyIndex, ExtendedPrivKey, ExtendedPubKey, KeySeed};
// /////////////////////////////////////////////////////////////////////////////////////////////////
fn unwrap_exc_or<T>(exc: Result<T, ()>, def: T) -> T { fn unwrap_exc_or<T>(exc: Result<T, ()>, def: T) -> T {
@ -601,6 +593,74 @@ pub extern "C" fn zcashlc_get_verified_balance(
unwrap_exc_or(res, -1) unwrap_exc_or(res, -1)
} }
/// Returns the verified transparent balance for the address, which ignores utxos that have been
/// received too recently and are not yet deemed spendable.
#[no_mangle]
pub extern "C" fn zcashlc_get_verified_transparent_balance(
db_data: *const u8,
db_data_len: usize,
address: *const c_char,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(NETWORK, 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)
.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(|anchor| {
(&db_data)
.get_unspent_transparent_utxos(&taddr, anchor - 10)
.map_err(|e| format_err!("Error while fetching verified transparent balance: {}", e))
})?
.iter()
.map(|utxo| utxo.value)
.sum::<Amount>();
Ok(amount.into())
});
unwrap_exc_or(res, -1)
}
/// Returns the verified transparent balance for the address, which ignores utxos that have been
/// received too recently and are not yet deemed spendable.
#[no_mangle]
pub extern "C" fn zcashlc_get_total_transparent_balance(
db_data: *const u8,
db_data_len: usize,
address: *const c_char,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(NETWORK, 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)
.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(|anchor| {
(&db_data)
.get_unspent_transparent_utxos(&taddr, anchor)
.map_err(|e| format_err!("Error while fetching total transparent balance: {}", e))
})?
.iter()
.map(|utxo| utxo.value)
.sum::<Amount>();
Ok(amount.into())
});
unwrap_exc_or(res, -1)
}
/// Returns the memo for a received note, if it is known and a valid UTF-8 string. /// 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 /// The note is identified by its row index in the `received_notes` table within the data
@ -761,6 +821,49 @@ pub extern "C" fn zcashlc_scan_blocks(
unwrap_exc_or_null(res) unwrap_exc_or_null(res)
} }
#[no_mangle]
pub extern "C" fn zcashlc_put_utxo(
db_data: *const u8,
db_data_len: usize,
address_str: *const c_char,
txid_bytes: *const u8,
txid_bytes_len: usize,
index: i32,
script_bytes: *const u8,
script_bytes_len: usize,
value: i64,
height: i32,
) -> bool {
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 addr = unsafe {CStr::from_ptr(address_str).to_str()? };
let txid_bytes = unsafe { slice::from_raw_parts(txid_bytes, txid_bytes_len) };
let mut txid = [0u8; 32];
txid.copy_from_slice(&txid_bytes);
let script_bytes = unsafe { slice::from_raw_parts(script_bytes, script_bytes_len) };
let mut script = [0u8; 32];
script.copy_from_slice(&script_bytes);
let address = TransparentAddress::decode(&NETWORK, &addr).unwrap();
let output = WalletTransparentOutput {
address: address,
outpoint: OutPoint::new(txid, index as u32),
script: script.to_vec(),
value: Amount::from_i64(value).unwrap(),
height: BlockHeight::from(height as u32),
};
match put_received_transparent_utxo(&mut db_data, &output) {
Ok(_) => Ok(true),
Err(e) => Err(format_err!("Error while inserting UTXO: {}", e)),
}
});
unwrap_exc_or(res, false)
}
#[no_mangle] #[no_mangle]
pub extern "C" fn zcashlc_decrypt_and_store_transaction( pub extern "C" fn zcashlc_decrypt_and_store_transaction(
db_data: *const u8, db_data: *const u8,
@ -911,31 +1014,27 @@ pub extern "C" fn zcashlc_vec_string_free(v: *mut *mut c_char, len: usize, capac
pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed( pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed(
seed: *const u8, seed: *const u8,
seed_len: usize, seed_len: usize,
account: i32,
index: i32,
) -> *mut c_char { ) -> *mut c_char {
let res = catch_panic(|| { let res = catch_panic(|| {
let seed = slice::from_raw_parts(seed, seed_len); let seed = slice::from_raw_parts(seed, seed_len);
let account = if account >= 0 {
account as u32
} else {
return Err(format_err!("account argument must be positive"));
};
// modified from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs let index = if index >= 0 {
index as u32
} else {
return Err(format_err!("index argument must be positive"));
};
let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index).unwrap();
let sk_wif = Wif::from_secret_key(&sk, true);
let ext_t_key = ExtendedPrivKey::with_seed(&seed).unwrap(); Ok(CString::new(sk_wif.0.to_string()).unwrap().into_raw())
let address_sk = ext_t_key
.derive_private_key(KeyIndex::hardened_from_normalize_index(44).unwrap())
.unwrap()
.derive_private_key(
KeyIndex::hardened_from_normalize_index(NETWORK.coin_type()).unwrap(),
)
.unwrap()
.derive_private_key(KeyIndex::hardened_from_normalize_index(0).unwrap())
.unwrap()
.derive_private_key(KeyIndex::Normal(0))
.unwrap()
.derive_private_key(KeyIndex::Normal(0))
.unwrap()
.private_key;
Ok(CString::new(address_sk.to_string()).unwrap().into_raw())
}); });
unwrap_exc_or_null(res) unwrap_exc_or_null(res)
} }
@ -945,82 +1044,52 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed(
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed( pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
seed: *const u8, seed: *const u8,
seed_len: usize, seed_len: usize,
account: i32,
index: i32,
) -> *mut c_char { ) -> *mut c_char {
let res = catch_panic(|| { let res = catch_panic(|| {
let seed = slice::from_raw_parts(seed, seed_len); let seed = slice::from_raw_parts(seed, seed_len);
let account = if account >= 0 {
// modified from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs account as u32
} else {
let ext_t_key = ExtendedPrivKey::with_seed(&seed).unwrap(); return Err(format_err!("account argument must be positive"));
let address_sk = ext_t_key
.derive_private_key(KeyIndex::hardened_from_normalize_index(44).unwrap())
.unwrap()
.derive_private_key(
KeyIndex::hardened_from_normalize_index(NETWORK.coin_type()).unwrap(),
)
.unwrap()
.derive_private_key(KeyIndex::hardened_from_normalize_index(0).unwrap())
.unwrap()
.derive_private_key(KeyIndex::Normal(0))
.unwrap()
.derive_private_key(KeyIndex::Normal(0))
.unwrap()
.private_key;
let private_key = match secp256k1::SecretKey::from_slice(&address_sk[..]) {
Ok(pk) => pk,
Err(e) => {
return Err(format_err!("error converting secret key {}",e));
},
}; };
let secp = Secp256k1::new();
let pk = PublicKey::from_secret_key(&secp, &private_key);
let mut hash160 = ripemd160::Ripemd160::new();
hash160.update(Sha256::digest(&pk.serialize()[..].to_vec()));
let address_string = hash160
.finalize()
.to_base58check(&NETWORK.b58_pubkey_address_prefix(), &[]);
Ok(CString::new(address_string).unwrap().into_raw()) let index = if index >= 0 {
index as u32
} else {
return Err(format_err!("index argument must be positive"));
};
let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index);
let taddr = derive_transparent_address_from_secret_key(sk.unwrap())
.encode(&NETWORK);
Ok(CString::new(taddr).unwrap().into_raw())
}); });
unwrap_exc_or_null(res) unwrap_exc_or_null(res)
} }
/// Derives a transparent address from the given seed /// Derives a transparent address from the given secret key enconded as a WIF string
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key( pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key(
tsk: *const c_char, tsk: *const c_char,
) -> *mut c_char { ) -> *mut c_char {
let res = catch_panic(|| { let res = catch_panic(|| {
let tsk = CStr::from_ptr(tsk).to_str()?; let tsk_wif = CStr::from_ptr(tsk).to_str()?;
// grab secret private key for t-funds let sk: SecretKey = (&Wif(tsk_wif.to_string())).try_into().expect("invalid private key WIF");
let sk = match secp256k1::key::SecretKey::from_str(&tsk) {
Ok(sk) => sk,
Err(e) => {
return Err(format_err!("Invalid Transparent Secret key: {}", e));
},
};
// derive the corresponding t-address // derive the corresponding t-address
let taddr =
Ok(CString::new(derive_transparent_address_from_secret_key(sk)).unwrap().into_raw()) derive_transparent_address_from_secret_key(sk)
.encode(&NETWORK);
Ok(CString::new(taddr).unwrap().into_raw())
}); });
unwrap_exc_or_null(res) unwrap_exc_or_null(res)
} }
fn derive_transparent_address_from_secret_key(secret_key: SecretKey) -> String {
let secp = Secp256k1::new();
let pk = PublicKey::from_secret_key(&secp, &secret_key);
let mut hash160 = ripemd160::Ripemd160::new();
hash160.update(Sha256::digest(&pk.serialize()[..].to_vec()));
hash160
.finalize()
.to_base58check(&NETWORK.b58_pubkey_address_prefix(), &[])
}
// //
// Helper code from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs // Helper code from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs
// //
@ -1051,204 +1120,10 @@ pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
h2.to_vec() h2.to_vec()
} }
//// Extremely Experimental: I'm not even a rust developer
///
/// psst, hey I have a Major in Social Sciences. Consider using something else
/// Creates a transaction paying the specified address from the given account.
///
/// Returns the row index of the newly-created transaction in the `transactions` table
/// within the data database. The caller can read the raw transaction bytes from the `raw`
/// column in order to broadcast the transaction to the network.
///
/// Do not call this multiple times in parallel, or you will generate transactions that
/// double-spend the same notes.
///
///
fn shield_funds<P: consensus::Parameters>(
db_cache: &BlockDB,
db_data: &WalletDB<P>,
account: u32,
tsk: &str,
extsk: &str,
memo: &str,
spend_params: &Path,
output_params: &Path,
) -> Result<i64,failure::Error> {
let target_height_and_anchor = match (&db_data).get_target_and_anchor_heights() {
Ok(Some(h)) => h,
Ok(None) => {
return Err(format_err!("No anchor and target heights found"));
},
Err(e) => {
return Err(format_err!("Error fetching anchor and target heights: {}", e));
},
};
// grab secret private key for t-funds
let sk = match secp256k1::key::SecretKey::from_str(&tsk) {
Ok(sk) => sk,
Err(e) => {
return Err(format_err!("Invalid Transparent Secret key: {}", e));
},
};
// derive the corresponding t-address
let t_addr_str = derive_transparent_address_from_secret_key(sk);
let extsk =
match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk)
{
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));
},
};
// derive own shielded address from the provided extended spending key
let z_address = extsk.default_address().unwrap().1;
let exfvk = ExtendedFullViewingKey::from(&extsk);
let ovk = exfvk.fvk.ovk;
let memo = match Memo::from_str(&memo) {
Ok(memo) => memo,
Err(_) => {
return Err(format_err!("Invalid memo input"));
}
};
// get latest height and anchor
let latest_scanned_height = target_height_and_anchor.0;
let latest_anchor = target_height_and_anchor.1;
// get UTXOs from DB
let utxos = match get_confirmed_utxos_for_address(&NETWORK, &db_cache, latest_anchor, &t_addr_str) {
Ok(u) => u,
Err(e) => {
return Err(format_err!("Error getting UTXOs {}",e));
},
};
let total_amount = match Amount::from_i64(utxos.iter().map(|u| i64::from(u.value)).sum::<i64>()) {
Ok(a) => a,
_ => {
return Err(format_err!("error collecting total amount from UTXOs"));
},
};
let fee = DEFAULT_FEE;
let target_value = fee + total_amount;
if fee >= total_amount {
return Err(format_err!("Insufficient verified funds (have {}, need {:?}). NOTE: funds need {} confirmations before they can be spent.",
u64::from(total_amount), target_value, target_height_and_anchor.0 + 1));
}
let amount_to_shield = total_amount - fee;
let prover = LocalTxProver::new(spend_params, output_params);
let mut builder = Builder::new(NETWORK, latest_scanned_height);
for utxo in utxos.iter() {
let outpoint = OutPoint::new(
utxo.txid.0,
utxo.index as u32
);
let coin = TxOut {
value: utxo.value.clone(),
script_pubkey: Script { 0: utxo.script.clone() },
};
match builder.add_transparent_input(sk.clone(), outpoint.clone(), coin.clone()) {
Ok(_) => (),
Err(e) => {
return Err(format_err!("error adding transparent input {}",e));
},
}
}
// there are no sapling notes so we set the change manually
builder.send_change_to(ovk, z_address.clone());
// add the sapling output to shield the funds
match builder.add_sapling_output(Some(ovk), z_address.clone(), amount_to_shield, Some(memo.clone())) {
Ok(_) =>(),
Err(e) => {
return Err(format_err!("Failed to add sapling output {}", e));
}
};
let consensus_branch_id = BranchId::for_height(&NETWORK, target_height_and_anchor.1);
let (tx, tx_metadata) = match builder
.build(consensus_branch_id, &prover) {
Ok(t) => t,
Err(e) => {
return Err(format_err!("Error building transaction {}",e));
},
};
// We only called add_sapling_output() once.
let output_index = match tx_metadata.output_index(0) {
Some(idx) => idx as i64,
None => {
return Err(format_err!("Output 0 should exist in the transaction"));
},
};
// Update the database atomically, to ensure the result is internally consistent.
let mut db_update = match (&db_data).get_update_ops() {
Ok(d) => d,
Err(e) => {
return Err(format_err!("error updating database with created tx {}",e));
},
};
db_update
.transactionally(|up| {
let created = time::OffsetDateTime::now_utc();
let tx_ref = up.put_tx_data(&tx, Some(created))?;
// Mark notes as spent.
//
// This locks the notes so they aren't selected again by a subsequent call to
// create_spend_to_address() before this transaction has been mined (at which point the notes
// get re-marked as spent).
//
// Assumes that create_spend_to_address() will never be called in parallel, which is a
// reasonable assumption for a light client such as a mobile phone.
for spend in &tx.shielded_spends {
up.mark_spent(tx_ref, &spend.nullifier)?;
}
up.insert_sent_note(
tx_ref,
output_index as usize,
AccountId(account),
&RecipientAddress::from(z_address),
amount_to_shield,
Some(memo),
)?;
// Return the row number of the transaction, so the caller can fetch it for sending.
Ok(tx_ref)
})
.map_err(|e| format_err!("error building updating data_db {}",e))
}
#[no_mangle] #[no_mangle]
pub extern "C" fn zcashlc_shield_funds( pub extern "C" fn zcashlc_shield_funds(
db_data: *const u8, db_data: *const u8,
db_data_len: usize, db_data_len: usize,
db_cache: *const u8,
db_cache_len: usize,
account: i32, account: i32,
tsk: *const c_char, tsk: *const c_char,
extsk: *const c_char, extsk: *const c_char,
@ -1261,13 +1136,16 @@ pub extern "C" fn zcashlc_shield_funds(
let res = catch_panic(|| { let res = catch_panic(|| {
let db_data = wallet_db(NETWORK, db_data, db_data_len)?; let db_data = wallet_db(NETWORK, db_data, db_data_len)?;
let db_cache = block_db(db_cache, db_cache_len)?; let mut update_ops = (&db_data)
.get_update_ops()
.map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
let account = if account >= 0 { let account = if account >= 0 {
account as u32 account as u32
} else { } else {
return Err(format_err!("account argument must be positive")); return Err(format_err!("account argument must be positive"));
}; };
let tsk = unsafe { CStr::from_ptr(tsk) }.to_str()?; let tsk_wif = unsafe { CStr::from_ptr(tsk) }.to_str()?;
let extsk = unsafe { CStr::from_ptr(extsk) }.to_str()?; let extsk = unsafe { CStr::from_ptr(extsk) }.to_str()?;
let memo = unsafe { CStr::from_ptr(memo) }.to_str()?; let memo = unsafe { CStr::from_ptr(memo) }.to_str()?;
let spend_params = Path::new(OsStr::from_bytes(unsafe { let spend_params = Path::new(OsStr::from_bytes(unsafe {
@ -1277,7 +1155,36 @@ pub extern "C" fn zcashlc_shield_funds(
slice::from_raw_parts(output_params, output_params_len) slice::from_raw_parts(output_params, output_params_len)
})); }));
shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params) //grab secret private key for t-funds
let sk:SecretKey = (&Wif(tsk_wif.to_string())).try_into()?;
let extsk =
match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk)
{
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 memo = match Memo::from_str(&memo) {
Ok(memo) => memo,
Err(_) => {
return Err(format_err!("Invalid memo input"));
}
};
// shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params)
shield_funds(&mut update_ops,
&NETWORK,
LocalTxProver::new(spend_params, output_params),
AccountId(account),
&sk,
&extsk,
&memo,
ANCHOR_OFFSET)
.map_err(|e| format_err!("Error while shielding transaction: {}", e))
}); });
unwrap_exc_or(res, -1) unwrap_exc_or(res, -1)
} }