[WIP] data access api compliance
This commit is contained in:
parent
2d76c96b42
commit
1affc50726
|
@ -98,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
|
@ -131,9 +131,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
|||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdcf67bb7ba7797a081cd19009948ab533af7c355d5caf1d08c777582d351e9c"
|
||||
checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1"
|
||||
|
||||
[[package]]
|
||||
name = "bellman"
|
||||
|
@ -307,15 +307,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.41"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -363,7 +357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
|
@ -546,7 +540,7 @@ version = "0.1.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"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"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
@ -601,13 +595,24 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "hdwallet"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35b15cc3c181a2aace485d56c784568a4ae6e34322287a2499549d4cda7af3e1"
|
||||
source = "git+https://github.com/nuttycom/hdwallet?rev=72f1f7a56c114eed484cefd6d402b7ef28158712#72f1f7a56c114eed484cefd6d402b7ef28158712"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"rand 0.7.3",
|
||||
"rand_core 0.6.2",
|
||||
"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]]
|
||||
|
@ -671,22 +676,22 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
|
@ -708,10 +713,11 @@ dependencies = [
|
|||
"cbindgen",
|
||||
"failure",
|
||||
"ffi_helpers",
|
||||
"hdwallet",
|
||||
"funty",
|
||||
"hdwallet 0.3.0",
|
||||
"hex",
|
||||
"ripemd160",
|
||||
"secp256k1 0.19.0",
|
||||
"secp256k1",
|
||||
"sha2 0.9.3",
|
||||
"time",
|
||||
"zcash_client_backend",
|
||||
|
@ -726,7 +732,7 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -792,6 +798,12 @@ version = "0.23.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
|
@ -849,24 +861,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "2.20.0"
|
||||
version = "2.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86473d5f16580f10b131a0bf0afb68f8e029d1835d33a00f37281b05694e5312"
|
||||
checksum = "73f72884896d22e0da0e5b266cb9a780b791f6c3b2f5beab6368d6cd4f0dbb86"
|
||||
|
||||
[[package]]
|
||||
name = "protobuf-codegen"
|
||||
version = "2.20.0"
|
||||
version = "2.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8b6ba4581fcd9c3ce3576f25e528467b0d3516e332884c0da6f2084fe59045f"
|
||||
checksum = "e8217a1652dbc91d19c509c558234145faed729191a966896414e5889f62d543"
|
||||
dependencies = [
|
||||
"protobuf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "protobuf-codegen-pure"
|
||||
version = "2.20.0"
|
||||
version = "2.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0cc5a64733bf127b466ca734a39ad1b123ac37bfe96c5a340fa6f5393dfd964"
|
||||
checksum = "1f239d71417bdc5f8d83c07aeb265f911346e5540a1a6c4285f9c3d1966ed6e3"
|
||||
dependencies = [
|
||||
"protobuf",
|
||||
"protobuf-codegen",
|
||||
|
@ -874,9 +886,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -908,7 +920,7 @@ checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
"rand_hc 0.3.0",
|
||||
]
|
||||
|
||||
|
@ -929,7 +941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -943,9 +955,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
]
|
||||
|
@ -965,7 +977,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||
dependencies = [
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -976,9 +988,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -1005,13 +1017,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",
|
||||
|
@ -1078,31 +1090,13 @@ version = "1.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "secp256k1"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb"
|
||||
dependencies = [
|
||||
"secp256k1-sys 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1-sys"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"secp256k1-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1151,9 +1145,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.61"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1185,7 +1179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"cpuid-bool",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug 0.3.0",
|
||||
|
@ -1205,9 +1199,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
|||
|
||||
[[package]]
|
||||
name = "standback"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c66a8cff4fa24853fdf6b51f75c6d7f8206d7c75cab4e467bcd7f25c2b1febe0"
|
||||
checksum = "a2beb4d1860a61f571530b3f855a1b538d0200f7871c63331ecd6f17b1f014f8"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
@ -1308,10 +1302,10 @@ version = "3.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rand 0.8.3",
|
||||
"redox_syscall 0.2.4",
|
||||
"redox_syscall 0.2.5",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1438,7 +1432,7 @@ version = "0.2.70"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
|
@ -1534,6 +1528,7 @@ dependencies = [
|
|||
"bs58",
|
||||
"ff",
|
||||
"group",
|
||||
"hdwallet 0.2.5",
|
||||
"hex",
|
||||
"jubjub",
|
||||
"nom",
|
||||
|
@ -1541,6 +1536,9 @@ dependencies = [
|
|||
"protobuf",
|
||||
"protobuf-codegen-pure",
|
||||
"rand_core 0.5.1",
|
||||
"ripemd160",
|
||||
"secp256k1",
|
||||
"sha2 0.9.3",
|
||||
"subtle",
|
||||
"time",
|
||||
"zcash_primitives",
|
||||
|
@ -1585,7 +1583,7 @@ dependencies = [
|
|||
"rand 0.7.3",
|
||||
"rand_core 0.5.1",
|
||||
"ripemd160",
|
||||
"secp256k1 0.19.0",
|
||||
"secp256k1",
|
||||
"sha2 0.9.3",
|
||||
"subtle",
|
||||
]
|
||||
|
|
18
Cargo.toml
18
Cargo.toml
|
@ -11,18 +11,19 @@ build = "rust/build.rs"
|
|||
failure = "0.1"
|
||||
ffi_helpers = "0.2"
|
||||
hex = "0.4"
|
||||
zcash_client_backend = "0.4"
|
||||
zcash_client_sqlite = "0.2.1"
|
||||
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"] }
|
||||
|
||||
#### Temporary additions: ####################################
|
||||
base58 = "0.1.0"
|
||||
sha2 = "0.9"
|
||||
bs58 = { version = "0.3", features = ["check"] }
|
||||
hdwallet = "0.2.2"
|
||||
hdwallet = "0.3.0"
|
||||
ripemd160 = "0.9"
|
||||
secp256k1 = "0.19"
|
||||
time = "0.2"
|
||||
funty = "=1.1.0"
|
||||
##############################################################
|
||||
|
||||
|
||||
|
@ -43,10 +44,10 @@ crate-type = ["staticlib"]
|
|||
lto = true
|
||||
|
||||
[patch.crates-io]
|
||||
#zcash_client_backend = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||
#zcash_client_sqlite = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||
#zcash_primitives = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||
#zcash_proofs = {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/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" }
|
||||
|
@ -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" }
|
||||
|
||||
[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"]
|
||||
|
|
|
@ -10,11 +10,11 @@ import Foundation
|
|||
import ZcashLightClientKit
|
||||
import MnemonicSwift
|
||||
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 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 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 {
|
||||
"\(host):\(port)"
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
}
|
||||
}
|
||||
|
||||
func balance(address: String, latestHeight: BlockHeight) throws -> UnshieldedBalance {
|
||||
func balance(address: String, latestHeight: BlockHeight) throws -> WalletBalance {
|
||||
|
||||
do {
|
||||
let confirmed = try dbProvider.connection().scalar(
|
||||
|
@ -142,7 +142,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
}
|
||||
}
|
||||
|
||||
struct TransparentBalance: UnshieldedBalance {
|
||||
struct TransparentBalance: WalletBalance {
|
||||
var confirmed: Int64
|
||||
var unconfirmed: Int64
|
||||
var address: String
|
||||
|
|
|
@ -7,16 +7,11 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public protocol UnshieldedBalance {
|
||||
var confirmed: Int64 { get set }
|
||||
var unconfirmed: Int64 { get set }
|
||||
}
|
||||
|
||||
protocol UnspentTransactionOutputRepository {
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -9,6 +9,34 @@
|
|||
import Foundation
|
||||
|
||||
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? {
|
||||
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
|
||||
}
|
||||
|
||||
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 memoBytes = memo ?? ""
|
||||
|
||||
|
@ -215,7 +243,6 @@ class ZcashRustBackend: ZcashRustBackendWelding {
|
|||
dbData.1,
|
||||
account,
|
||||
[CChar](extsk.utf8CString),
|
||||
consensusBranchId,
|
||||
[CChar](to.utf8CString),
|
||||
value,
|
||||
[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 {
|
||||
let dbData = dbData.osStr()
|
||||
let dbCache = dbCache.osStr()
|
||||
let memoBytes = memo ?? ""
|
||||
|
||||
return zcashlc_shield_funds(dbData.0,
|
||||
dbData.1,
|
||||
dbCache.0,
|
||||
dbCache.1,
|
||||
account,
|
||||
tsk,
|
||||
extsk,
|
||||
memoBytes,
|
||||
[CChar](tsk.utf8CString),
|
||||
[CChar](extsk.utf8CString),
|
||||
[CChar](memoBytes.utf8CString),
|
||||
spendParamsPath,
|
||||
UInt(spendParamsPath.lengthOfBytes(using: .utf8)),
|
||||
outputParamsPath,
|
||||
|
@ -329,9 +353,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
|
|||
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() {
|
||||
throw error
|
||||
}
|
||||
|
@ -343,8 +367,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
|
|||
return tAddr
|
||||
}
|
||||
|
||||
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8]) throws -> String? {
|
||||
guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count)) else {
|
||||
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), Int32(account), Int32(index)) else {
|
||||
if let error = lastError() {
|
||||
throw error
|
||||
}
|
||||
|
|
|
@ -165,6 +165,18 @@ public protocol ZcashRustBackendWelding {
|
|||
*/
|
||||
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
|
||||
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
|
||||
- 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.
|
||||
|
@ -253,14 +265,14 @@ public protocol ZcashRustBackendWelding {
|
|||
- Returns: an optional String containing the transparent address
|
||||
- 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
|
||||
- Parameter seed: an array of bytes containing the seed
|
||||
- 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
|
||||
|
|
|
@ -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
|
||||
|
@ -170,6 +174,11 @@ public protocol Synchronizer {
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -178,12 +187,13 @@ public protocol Synchronizer {
|
|||
/**
|
||||
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
|
||||
*/
|
||||
func getUnshieldedBalance(address: String) throws -> UnshieldedBalance
|
||||
func getTransparentBalance(address: String) throws -> WalletBalance
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -77,12 +77,12 @@ public protocol KeyDeriving {
|
|||
// 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.
|
||||
// - 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
|
||||
*/
|
||||
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
|
||||
|
@ -215,9 +215,9 @@ public class DerivationTool: KeyDeriving {
|
|||
// 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.
|
||||
// - 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 {
|
||||
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
|
||||
}
|
||||
return zaddr
|
||||
|
@ -237,9 +237,9 @@ public class DerivationTool: KeyDeriving {
|
|||
- KeyDerivationErrors.derivationError with the underlying error when it fails
|
||||
- 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 {
|
||||
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
|
||||
}
|
||||
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 {
|
||||
do {
|
||||
guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk) else {
|
||||
|
|
|
@ -84,12 +84,9 @@ class WalletTransactionEncoder: TransactionEncoder {
|
|||
throw RustWeldingError.genericError(message: "could not convert \(scannedHeight)")
|
||||
}
|
||||
|
||||
let consensusBranchId = try rustBackend.consensusBranchIdFor(height: latestHeight)
|
||||
|
||||
let txId = rustBackend.createToAddress(dbData: self.dataDbURL,
|
||||
account: Int32(accountIndex),
|
||||
extsk: spendingKey,
|
||||
consensusBranchId: consensusBranchId,
|
||||
to: address,
|
||||
value: Int64(zatoshi),
|
||||
memo: memo,
|
||||
|
|
|
@ -495,7 +495,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
/**
|
||||
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
|
||||
|
||||
guard let self = self else { return }
|
||||
|
@ -515,7 +515,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
/**
|
||||
gets the last stored unshielded balance
|
||||
*/
|
||||
public func getUnshieldedBalance(address: String) throws -> UnshieldedBalance {
|
||||
public func getTransparentBalance(address: String) throws -> WalletBalance {
|
||||
do {
|
||||
let latestHeight = try self.latestDownloadedHeight()
|
||||
let cachedBalance = try utxoRepository.balance(address: address, latestHeight: latestHeight)
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -97,7 +100,10 @@ char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed, uintptr_
|
|||
*
|
||||
* 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.
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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,
|
||||
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.
|
||||
*
|
||||
|
@ -208,6 +230,17 @@ bool zcashlc_is_valid_viewing_key(const char *key);
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -239,8 +272,6 @@ int32_t zcashlc_scan_blocks(const uint8_t *db_cache,
|
|||
|
||||
int64_t zcashlc_shield_funds(const uint8_t *db_data,
|
||||
uintptr_t db_data_len,
|
||||
const uint8_t *db_cache,
|
||||
uintptr_t db_cache_len,
|
||||
int32_t account,
|
||||
const char *tsk,
|
||||
const char *extsk,
|
||||
|
|
507
rust/src/lib.rs
507
rust/src/lib.rs
|
@ -8,42 +8,47 @@ use std::slice;
|
|||
use std::str::FromStr;
|
||||
use zcash_client_backend::{
|
||||
address::RecipientAddress,
|
||||
wallet::AccountId,
|
||||
data_api::{
|
||||
chain::{scan_cached_blocks, validate_chain},
|
||||
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,
|
||||
},
|
||||
encoding::{
|
||||
decode_extended_full_viewing_key, decode_extended_spending_key,
|
||||
encode_extended_full_viewing_key, encode_extended_spending_key, encode_payment_address,
|
||||
AddressCodec,
|
||||
decode_extended_full_viewing_key,
|
||||
decode_extended_spending_key,
|
||||
encode_extended_full_viewing_key,
|
||||
encode_extended_spending_key,
|
||||
encode_payment_address,
|
||||
},
|
||||
keys::spending_key,
|
||||
wallet::OvkPolicy,
|
||||
keys::{
|
||||
derive_secret_key_from_seed,
|
||||
derive_transparent_address_from_secret_key,
|
||||
spending_key, Wif,
|
||||
},
|
||||
wallet::{AccountId, OvkPolicy, WalletTransparentOutput},
|
||||
};
|
||||
use zcash_client_sqlite::{
|
||||
error::SqliteClientError,
|
||||
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,
|
||||
chain::get_confirmed_utxos_for_address,
|
||||
|
||||
};
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{self,BlockHeight, BranchId, Parameters},
|
||||
note_encryption::Memo,
|
||||
transaction::components::{
|
||||
amount::DEFAULT_FEE,
|
||||
Amount,
|
||||
OutPoint,
|
||||
TxOut
|
||||
transaction::{
|
||||
Transaction,
|
||||
components::{Amount, OutPoint},
|
||||
},
|
||||
legacy::Script,
|
||||
transaction::builder::Builder,
|
||||
transaction::Transaction,
|
||||
|
||||
zip32::{ExtendedFullViewingKey},
|
||||
legacy::TransparentAddress,
|
||||
};
|
||||
|
||||
#[cfg(feature = "mainnet")]
|
||||
|
@ -52,23 +57,10 @@ use zcash_primitives::consensus::{MainNetwork, MAIN_NETWORK};
|
|||
use zcash_primitives::consensus::{TestNetwork, TEST_NETWORK};
|
||||
|
||||
use zcash_proofs::prover::LocalTxProver;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Temporary Imports
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use base58::ToBase58;
|
||||
use sha2::{Digest, Sha256};
|
||||
// use zcash_primitives::legacy::TransparentAddress;
|
||||
use hdwallet::{ExtendedPrivKey, KeyIndex};
|
||||
use secp256k1::{
|
||||
Secp256k1,
|
||||
key::{PublicKey, SecretKey},
|
||||
};
|
||||
|
||||
|
||||
// use crate::extended_key::{key_index::KeyIndex, ExtendedPrivKey, ExtendedPubKey, KeySeed};
|
||||
// /////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
use secp256k1::key::SecretKey;
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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)
|
||||
}
|
||||
|
||||
#[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]
|
||||
pub extern "C" fn zcashlc_decrypt_and_store_transaction(
|
||||
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(
|
||||
seed: *const u8,
|
||||
seed_len: usize,
|
||||
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 {
|
||||
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();
|
||||
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())
|
||||
Ok(CString::new(sk_wif.0.to_string()).unwrap().into_raw())
|
||||
});
|
||||
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(
|
||||
seed: *const u8,
|
||||
seed_len: usize,
|
||||
account: i32,
|
||||
index: i32,
|
||||
) -> *mut c_char {
|
||||
|
||||
let res = catch_panic(|| {
|
||||
let seed = slice::from_raw_parts(seed, seed_len);
|
||||
|
||||
// modified from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs
|
||||
|
||||
let ext_t_key = ExtendedPrivKey::with_seed(&seed).unwrap();
|
||||
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 account = if account >= 0 {
|
||||
account as u32
|
||||
} else {
|
||||
return Err(format_err!("account argument must be positive"));
|
||||
};
|
||||
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)
|
||||
}
|
||||
|
||||
/// Derives a transparent address from the given seed
|
||||
/// Derives a transparent address from the given secret key enconded as a WIF string
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key(
|
||||
tsk: *const c_char,
|
||||
) -> *mut c_char {
|
||||
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 = match secp256k1::key::SecretKey::from_str(&tsk) {
|
||||
Ok(sk) => sk,
|
||||
Err(e) => {
|
||||
return Err(format_err!("Invalid Transparent Secret key: {}", e));
|
||||
},
|
||||
};
|
||||
let sk: SecretKey = (&Wif(tsk_wif.to_string())).try_into().expect("invalid private key WIF");
|
||||
|
||||
// derive the corresponding t-address
|
||||
|
||||
Ok(CString::new(derive_transparent_address_from_secret_key(sk)).unwrap().into_raw())
|
||||
let taddr =
|
||||
derive_transparent_address_from_secret_key(sk)
|
||||
.encode(&NETWORK);
|
||||
Ok(CString::new(taddr).unwrap().into_raw())
|
||||
});
|
||||
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
|
||||
//
|
||||
|
@ -1051,204 +1120,10 @@ pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
|
|||
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]
|
||||
pub extern "C" fn zcashlc_shield_funds(
|
||||
db_data: *const u8,
|
||||
db_data_len: usize,
|
||||
db_cache: *const u8,
|
||||
db_cache_len: usize,
|
||||
account: i32,
|
||||
tsk: *const c_char,
|
||||
extsk: *const c_char,
|
||||
|
@ -1261,13 +1136,16 @@ pub extern "C" fn zcashlc_shield_funds(
|
|||
let res = catch_panic(|| {
|
||||
|
||||
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 {
|
||||
account as u32
|
||||
} else {
|
||||
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 memo = unsafe { CStr::from_ptr(memo) }.to_str()?;
|
||||
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)
|
||||
}));
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue