[WIP] shield funds PoC
This commit is contained in:
parent
0c9f3cb5ef
commit
d75d5cb3ee
|
@ -49,9 +49,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.4.6"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c"
|
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
|
@ -340,9 +340,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_fn"
|
name = "const_fn"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
|
checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "constant_time_eq"
|
name = "constant_time_eq"
|
||||||
|
@ -429,7 +429,7 @@ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equihash"
|
name = "equihash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/nuttycom/librustzcash?branch=data_access_api#e96578195adfe0a80bc4be897e72d89813ea7387"
|
source = "git+https://github.com/pacu/librustzcash?branch=autoshield-poc#dc99e1e130e859e5f17dbdbb55cb0f505ffb37e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -597,14 +597,14 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"rand",
|
"rand",
|
||||||
"ring",
|
"ring",
|
||||||
"secp256k1",
|
"secp256k1 0.17.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
@ -674,9 +674,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.80"
|
version = "0.2.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
|
@ -701,8 +701,9 @@ dependencies = [
|
||||||
"hdwallet",
|
"hdwallet",
|
||||||
"hex",
|
"hex",
|
||||||
"ripemd160",
|
"ripemd160",
|
||||||
"secp256k1",
|
"secp256k1 0.17.2",
|
||||||
"sha2 0.9.2",
|
"sha2 0.9.2",
|
||||||
|
"time",
|
||||||
"zcash_client_backend",
|
"zcash_client_backend",
|
||||||
"zcash_client_sqlite",
|
"zcash_client_sqlite",
|
||||||
"zcash_primitives",
|
"zcash_primitives",
|
||||||
|
@ -863,9 +864,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -971,9 +972,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.24.1"
|
version = "0.24.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e3d4791ab5517217f51216a84a688b53c1ebf7988736469c538d02f46ddba68"
|
checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
|
@ -1024,7 +1025,16 @@ version = "0.17.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
|
checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"secp256k1-sys",
|
"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]]
|
[[package]]
|
||||||
|
@ -1036,6 +1046,15 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secp256k1-sys"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -1053,18 +1072,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.117"
|
version = "1.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
|
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.117"
|
version = "1.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
|
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1115,9 +1134,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85"
|
checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
|
@ -1197,15 +1216,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
|
checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.53"
|
version = "1.0.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
|
checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1287,9 +1306,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.7"
|
version = "0.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
|
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -1326,9 +1345,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.10"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
|
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
|
@ -1443,7 +1462,7 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_client_backend"
|
name = "zcash_client_backend"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/nuttycom/librustzcash?branch=data_access_api#e96578195adfe0a80bc4be897e72d89813ea7387"
|
source = "git+https://github.com/pacu/librustzcash?branch=autoshield-poc#dc99e1e130e859e5f17dbdbb55cb0f505ffb37e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.12.3",
|
"base64 0.12.3",
|
||||||
"bech32",
|
"bech32",
|
||||||
|
@ -1466,7 +1485,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_client_sqlite"
|
name = "zcash_client_sqlite"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "git+https://github.com/nuttycom/librustzcash?branch=data_access_api#e96578195adfe0a80bc4be897e72d89813ea7387"
|
source = "git+https://github.com/pacu/librustzcash?branch=autoshield-poc#dc99e1e130e859e5f17dbdbb55cb0f505ffb37e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bech32",
|
"bech32",
|
||||||
"bs58",
|
"bs58",
|
||||||
|
@ -1484,7 +1503,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_primitives"
|
name = "zcash_primitives"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/nuttycom/librustzcash?branch=data_access_api#e96578195adfe0a80bc4be897e72d89813ea7387"
|
source = "git+https://github.com/pacu/librustzcash?branch=autoshield-poc#dc99e1e130e859e5f17dbdbb55cb0f505ffb37e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
|
@ -1503,6 +1522,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
"ripemd160",
|
||||||
|
"secp256k1 0.19.0",
|
||||||
"sha2 0.9.2",
|
"sha2 0.9.2",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
@ -1510,7 +1531,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_proofs"
|
name = "zcash_proofs"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/nuttycom/librustzcash?branch=data_access_api#e96578195adfe0a80bc4be897e72d89813ea7387"
|
source = "git+https://github.com/pacu/librustzcash?branch=autoshield-poc#dc99e1e130e859e5f17dbdbb55cb0f505ffb37e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bellman",
|
"bellman",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -13,7 +13,7 @@ ffi_helpers = "0.2"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
zcash_client_backend = "0.4"
|
zcash_client_backend = "0.4"
|
||||||
zcash_client_sqlite = "0.2.1"
|
zcash_client_sqlite = "0.2.1"
|
||||||
zcash_primitives = "0.4"
|
zcash_primitives = { version = "0.4", features = ["transparent-inputs"] }
|
||||||
|
|
||||||
#### Temporary additions: ####################################
|
#### Temporary additions: ####################################
|
||||||
base58 = "0.1.0"
|
base58 = "0.1.0"
|
||||||
|
@ -22,8 +22,10 @@ bs58 = { version = "0.3", features = ["check"] }
|
||||||
hdwallet = "0.2.2"
|
hdwallet = "0.2.2"
|
||||||
ripemd160 = "0.9"
|
ripemd160 = "0.9"
|
||||||
secp256k1 = "0.17.2"
|
secp256k1 = "0.17.2"
|
||||||
|
time = "0.2"
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
|
|
||||||
[dependencies.zcash_proofs]
|
[dependencies.zcash_proofs]
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
@ -41,10 +43,10 @@ crate-type = ["staticlib"]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
zcash_client_backend = {git = "https://github.com/nuttycom/librustzcash", branch = "data_access_api"}
|
zcash_client_backend = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||||
zcash_client_sqlite = {git = "https://github.com/nuttycom/librustzcash", branch = "data_access_api"}
|
zcash_client_sqlite = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||||
zcash_primitives = {git = "https://github.com/nuttycom/librustzcash", branch = "data_access_api"}
|
zcash_primitives = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||||
zcash_proofs = {git = "https://github.com/nuttycom/librustzcash", branch = "data_access_api"}
|
zcash_proofs = {git = "https://github.com/pacu/librustzcash", branch = "autoshield-poc" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
mainnet = ["zcash_client_sqlite/mainnet"]
|
mainnet = ["zcash_client_sqlite/mainnet"]
|
||||||
|
|
|
@ -3,6 +3,31 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
int64_t zcashlc_autoshield_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,
|
||||||
|
const char *memo,
|
||||||
|
const uint8_t *spend_params,
|
||||||
|
uintptr_t spend_params_len,
|
||||||
|
const uint8_t *output_params,
|
||||||
|
uintptr_t output_params_len);
|
||||||
|
|
||||||
int32_t zcashlc_branch_id_for_height(int32_t height);
|
int32_t zcashlc_branch_id_for_height(int32_t height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,10 +5,11 @@ use std::env;
|
||||||
fn main() {
|
fn main() {
|
||||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||||
|
|
||||||
cbindgen::Builder::new()
|
if let Ok(b) = cbindgen::Builder::new()
|
||||||
.with_crate(crate_dir)
|
.with_crate(crate_dir)
|
||||||
.with_language(cbindgen::Language::C)
|
.with_language(cbindgen::Language::C)
|
||||||
.generate()
|
.generate() {
|
||||||
.expect("Unable to generate bindings")
|
b.write_to_file("ZcashLightClientKit/zcashlc/zcashlc.h");
|
||||||
.write_to_file("ZcashLightClientKit/zcashlc/zcashlc.h");
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
312
rust/src/lib.rs
312
rust/src/lib.rs
|
@ -25,13 +25,22 @@ use zcash_client_backend::{
|
||||||
use zcash_client_sqlite::{
|
use zcash_client_sqlite::{
|
||||||
wallet::init::{init_accounts_table, init_blocks_table, init_data_database},
|
wallet::init::{init_accounts_table, init_blocks_table, init_data_database},
|
||||||
BlockDB, NoteId, WalletDB,
|
BlockDB, NoteId, WalletDB,
|
||||||
|
wallet::{UnspentTransactionOutput, get_utxos},
|
||||||
};
|
};
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{BlockHeight, BranchId, Parameters},
|
consensus::{BlockHeight, BranchId, Parameters},
|
||||||
note_encryption::Memo,
|
note_encryption::Memo,
|
||||||
transaction::{components::Amount, Transaction},
|
transaction::components::{
|
||||||
zip32::ExtendedFullViewingKey,
|
amount::DEFAULT_FEE,
|
||||||
|
Amount,
|
||||||
|
OutPoint,
|
||||||
|
TxOut
|
||||||
|
},
|
||||||
|
legacy::Script,
|
||||||
|
transaction::builder::Builder,
|
||||||
|
transaction::Transaction,
|
||||||
|
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "mainnet")]
|
#[cfg(feature = "mainnet")]
|
||||||
|
@ -49,7 +58,10 @@ use base58::ToBase58;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
// use zcash_primitives::legacy::TransparentAddress;
|
// use zcash_primitives::legacy::TransparentAddress;
|
||||||
use hdwallet::{ExtendedPrivKey, KeyIndex};
|
use hdwallet::{ExtendedPrivKey, KeyIndex};
|
||||||
use secp256k1::{PublicKey, Secp256k1};
|
use secp256k1::{
|
||||||
|
Secp256k1,
|
||||||
|
key::{PublicKey, SecretKey},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// use crate::extended_key::{key_index::KeyIndex, ExtendedPrivKey, ExtendedPubKey, KeySeed};
|
// use crate::extended_key::{key_index::KeyIndex, ExtendedPrivKey, ExtendedPubKey, KeySeed};
|
||||||
|
@ -314,15 +326,25 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
|
||||||
} else {
|
} else {
|
||||||
return Err(format_err!("accounts argument must be greater than zero"));
|
return Err(format_err!("accounts argument must be greater than zero"));
|
||||||
};
|
};
|
||||||
let address = spending_key(&seed, NETWORK.coin_type(), account_index)
|
let address_str = deriveShieldedAddressFromSeed(&NETWORK, &seed, account_index);
|
||||||
.default_address()
|
|
||||||
.unwrap()
|
|
||||||
.1;
|
|
||||||
let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address);
|
|
||||||
Ok(CString::new(address_str).unwrap().into_raw())
|
Ok(CString::new(address_str).unwrap().into_raw())
|
||||||
});
|
});
|
||||||
unwrap_exc_or_null(res)
|
unwrap_exc_or_null(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deriveShieldedAddressFromSeed<P: Parameters>(params: &P, seed: &[u8], account_index: u32) -> String {
|
||||||
|
let address = spending_key(&seed, NETWORK.coin_type(), account_index)
|
||||||
|
.default_address()
|
||||||
|
.unwrap()
|
||||||
|
.1;
|
||||||
|
encode_payment_address(params.hrp_sapling_payment_address(), &address)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deriveShieldedAddressFromSpendingKey<P: Parameters>(params: &P, extsk: &ExtendedSpendingKey) -> String {
|
||||||
|
let address = extsk.default_address().unwrap().1;
|
||||||
|
encode_payment_address(params.hrp_sapling_payment_address(), &address)
|
||||||
|
}
|
||||||
|
|
||||||
/// derives a shielded address from the given viewing key.
|
/// derives a shielded address from the given viewing key.
|
||||||
/// call zcashlc_string_free with the returned pointer when done using it
|
/// call zcashlc_string_free with the returned pointer when done using it
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -366,17 +388,16 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key(
|
||||||
Ok(Some(extsk)) => ExtendedFullViewingKey::from(&extsk),
|
Ok(Some(extsk)) => ExtendedFullViewingKey::from(&extsk),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(format_err!("Deriving viewing key from spending key returned no results. Encoding was valid but type was incorrect."));
|
return Err(format_err!("Deriving viewing key from spending key returned no results. Encoding was valid but type was incorrect."));
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format_err!(
|
return Err(format_err!(
|
||||||
"Error while deriving viewing key from spending key: {}",
|
"Error while deriving viewing key from spending key: {}",
|
||||||
e
|
e
|
||||||
));
|
));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoded =
|
let encoded = encode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &extfvk);
|
||||||
encode_extended_full_viewing_key(NETWORK.hrp_sapling_extended_full_viewing_key(), &extfvk);
|
|
||||||
|
|
||||||
Ok(CString::new(encoded).unwrap().into_raw())
|
Ok(CString::new(encoded).unwrap().into_raw())
|
||||||
});
|
});
|
||||||
|
@ -456,32 +477,28 @@ pub extern "C" fn zcashlc_get_address(
|
||||||
pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char) -> bool {
|
pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char) -> bool {
|
||||||
let res = catch_panic(|| {
|
let res = catch_panic(|| {
|
||||||
let addr = CStr::from_ptr(address).to_str()?;
|
let addr = CStr::from_ptr(address).to_str()?;
|
||||||
|
Ok(is_valid_shielded_address(&addr))
|
||||||
match RecipientAddress::decode(&NETWORK, &addr) {
|
|
||||||
Some(addr) => match addr {
|
|
||||||
RecipientAddress::Shielded(_) => Ok(true),
|
|
||||||
RecipientAddress::Transparent(_) => Ok(false),
|
|
||||||
},
|
|
||||||
None => Err(format_err!("Address is for the wrong network")),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
unwrap_exc_or(res, false)
|
unwrap_exc_or(res, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_valid_shielded_address(address: &str) -> bool {
|
||||||
|
match RecipientAddress::decode(&NETWORK, &address) {
|
||||||
|
Some(addr) => match addr {
|
||||||
|
RecipientAddress::Shielded(_) => true,
|
||||||
|
RecipientAddress::Transparent(_) => false,
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when the address is valid and transparent.
|
/// Returns true when the address is valid and transparent.
|
||||||
/// Returns false in any other case
|
/// Returns false in any other case
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char) -> bool {
|
pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char) -> bool {
|
||||||
let res = catch_panic(|| {
|
let res = catch_panic(|| {
|
||||||
let addr = CStr::from_ptr(address).to_str()?;
|
let addr = CStr::from_ptr(address).to_str()?;
|
||||||
|
Ok(is_valid_transparent_address(&addr))
|
||||||
match RecipientAddress::decode(&NETWORK, &addr) {
|
|
||||||
Some(addr) => match addr {
|
|
||||||
RecipientAddress::Shielded(_) => Ok(false),
|
|
||||||
RecipientAddress::Transparent(_) => Ok(true),
|
|
||||||
},
|
|
||||||
None => Err(format_err!("Address is for the wrong network")),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
unwrap_exc_or(res, false)
|
unwrap_exc_or(res, false)
|
||||||
}
|
}
|
||||||
|
@ -501,6 +518,16 @@ pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> boo
|
||||||
});
|
});
|
||||||
unwrap_exc_or(res, false)
|
unwrap_exc_or(res, false)
|
||||||
}
|
}
|
||||||
|
fn is_valid_transparent_address(address: &str) -> bool {
|
||||||
|
match RecipientAddress::decode(&NETWORK, &address) {
|
||||||
|
Some(addr) => match addr {
|
||||||
|
RecipientAddress::Shielded(_) => false,
|
||||||
|
RecipientAddress::Transparent(_) => true,
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the balance for the account, including all unspent notes that we know about.
|
/// Returns the balance for the account, including all unspent notes that we know about.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn zcashlc_get_balance(db_data: *const u8, db_data_len: usize, account: i32) -> i64 {
|
pub extern "C" fn zcashlc_get_balance(db_data: *const u8, db_data_len: usize, account: i32) -> i64 {
|
||||||
|
@ -785,17 +812,17 @@ pub extern "C" fn zcashlc_create_to_address(
|
||||||
Ok(Some(extsk)) => extsk,
|
Ok(Some(extsk)) => extsk,
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(format_err!("ExtendedSpendingKey is for the wrong network"));
|
return Err(format_err!("ExtendedSpendingKey is for the wrong network"));
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
|
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let to = match RecipientAddress::decode(&NETWORK, &to) {
|
let to = match RecipientAddress::decode(&NETWORK, &to) {
|
||||||
Some(to) => to,
|
Some(to) => to,
|
||||||
None => {
|
None => {
|
||||||
return Err(format_err!("PaymentAddress is for the wrong network"));
|
return Err(format_err!("PaymentAddress is for the wrong network"));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
|
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
|
||||||
|
@ -931,6 +958,17 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
|
||||||
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
|
||||||
//
|
//
|
||||||
|
@ -959,4 +997,216 @@ pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
|
||||||
let h1 = Sha256::digest(&payload);
|
let h1 = Sha256::digest(&payload);
|
||||||
let h2 = Sha256::digest(&h1);
|
let h2 = Sha256::digest(&h1);
|
||||||
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.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn zcashlc_autoshield_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,
|
||||||
|
memo: *const c_char,
|
||||||
|
spend_params: *const u8,
|
||||||
|
spend_params_len: usize,
|
||||||
|
output_params: *const u8,
|
||||||
|
output_params_len: usize,
|
||||||
|
) -> i64 {
|
||||||
|
let res = catch_panic(|| {
|
||||||
|
|
||||||
|
let db_data = wallet_db(db_data, db_data_len)?;
|
||||||
|
let db_cache = block_db(db_cache, db_cache_len)?;
|
||||||
|
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 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 {
|
||||||
|
slice::from_raw_parts(spend_params, spend_params_len)
|
||||||
|
}));
|
||||||
|
let output_params = Path::new(OsStr::from_bytes(unsafe {
|
||||||
|
slice::from_raw_parts(output_params, output_params_len)
|
||||||
|
}));
|
||||||
|
|
||||||
|
let anchor_and_height = match (&db_data).get_target_and_anchor_heights() {
|
||||||
|
Ok(Some(h)) => h,
|
||||||
|
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 t_addr = match RecipientAddress::decode(&NETWORK, &t_addr_str) {
|
||||||
|
Some(to) => to,
|
||||||
|
None => {
|
||||||
|
return Err(format_err!("PaymentAddress is for the wrong network"));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
// get UTXOs from DB
|
||||||
|
let utxos = match get_utxos(&NETWORK, &db_cache) {
|
||||||
|
Ok(u) => u
|
||||||
|
};
|
||||||
|
|
||||||
|
// verify that the addresses of the UTXOs are correspond to the given t-address
|
||||||
|
let distinctAddresses: Vec<UnspentTransactionOutput> = utxos.into_iter().filter(|utxo| utxo.address != t_addr).collect();
|
||||||
|
|
||||||
|
if distinctAddresses.len() > 0 {
|
||||||
|
return Err(format_err!("one or more UTXOs correspond to other addresses that don't match the provided SecretKey"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that the utxos are confirmed
|
||||||
|
|
||||||
|
let latest_scanned_height = anchor_and_height.1;
|
||||||
|
let latest_anchor = anchor_and_height.0;
|
||||||
|
let unconfirmed_funds: Vec<BlockHeight> = utxos.iter().map(|u| u.height).filter(|h| h > &latest_anchor).collect();
|
||||||
|
|
||||||
|
if unconfirmed_funds.len() > 0 {
|
||||||
|
return Err(format_err!("one or more UTXOs are unconfirmed "));
|
||||||
|
}
|
||||||
|
|
||||||
|
let total_amount = utxos.iter().map(|u| u.value).sum();
|
||||||
|
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, anchor_and_height.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);
|
||||||
|
|
||||||
|
utxos.iter().map(|utxo| {
|
||||||
|
let outpoint = OutPoint::new(
|
||||||
|
utxo.txid.0,
|
||||||
|
utxo.index as u32
|
||||||
|
);
|
||||||
|
|
||||||
|
let coin = TxOut {
|
||||||
|
value: utxo.value.clone(),
|
||||||
|
script_pubkey: utxo.script.clone(),
|
||||||
|
};
|
||||||
|
builder.add_transparent_input(sk.clone(), outpoint.clone(), coin.clone())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
.map_err(|e| format_err!("Error adding transparent output {}",e));
|
||||||
|
|
||||||
|
// there are no sapling notes so we set the change manually
|
||||||
|
builder.send_change_to(ovk, z_address);
|
||||||
|
|
||||||
|
let recipient = RecipientAddress::Shielded(z_address);
|
||||||
|
|
||||||
|
// add the sapling output to shield the funds
|
||||||
|
builder.add_sapling_output(Some(ovk), z_address.clone(), amount_to_shield, Some(memo));
|
||||||
|
let consensus_branch_id = BranchId::for_height(&NETWORK, anchor_and_height.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 = (&db_data).get_update_ops().map_err(|e| e.into())?;
|
||||||
|
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(
|
||||||
|
&NETWORK,
|
||||||
|
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))
|
||||||
|
});
|
||||||
|
unwrap_exc_or(res, -1)
|
||||||
}
|
}
|
Loading…
Reference in New Issue