diff --git a/Cargo.lock b/Cargo.lock index ec1d685..60a4fd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher 0.3.0", "cpufeatures", "ctr 0.8.0", @@ -46,7 +46,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher 0.4.4", "cpufeatures", ] @@ -68,7 +68,7 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "version_check", "zerocopy", @@ -302,7 +302,7 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -333,12 +333,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - [[package]] name = "base64ct" version = "1.0.1" @@ -381,29 +375,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.5.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.49", - "which", -] - [[package]] name = "bip0039" version = "0.10.1" @@ -483,16 +454,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -[[package]] -name = "bitflags-serde-legacy" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b64e60c28b6d25ad92e8b367801ff9aa12b41d05fc8798055d296bace4a60cc" -dependencies = [ - "bitflags 2.5.0", - "serde", -] - [[package]] name = "bitvec" version = "1.0.1" @@ -557,7 +518,7 @@ dependencies = [ "arrayref", "arrayvec", "cc", - "cfg-if 1.0.0", + "cfg-if", "constant_time_eq", "digest 0.10.7", ] @@ -650,15 +611,6 @@ dependencies = [ "x25519-dalek 2.0.1", ] -[[package]] -name = "bridgetree" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbfcb6c5a091e80cb3d3b0c1a7f126af4631cd5065b1f9929b139f1be8f3fb62" -dependencies = [ - "incrementalmerkletree", -] - [[package]] name = "bs58" version = "0.4.0" @@ -675,16 +627,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "bstr" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "build_utils" version = "0.1.0" @@ -696,12 +638,6 @@ version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - [[package]] name = "byte-tools" version = "0.3.1" @@ -743,17 +679,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cbc" version = "0.1.2" @@ -774,21 +699,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -811,7 +721,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher 0.4.4", "cpufeatures", ] @@ -837,10 +747,7 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", - "serde", - "wasm-bindgen", "windows-targets 0.52.0", ] @@ -864,17 +771,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "4.5.1" @@ -934,16 +830,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.0" @@ -1034,7 +920,7 @@ checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" dependencies = [ "digest 0.10.7", "ecdsa", - "ed25519-zebra 3.1.0", + "ed25519-zebra", "k256", "rand_core 0.6.4", "thiserror", @@ -1138,7 +1024,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1280,14 +1166,12 @@ version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest 0.10.7", "fiat-crypto", "platforms", "rustc_version", - "serde", "subtle 2.4.1", "zeroize", ] @@ -1412,89 +1296,13 @@ dependencies = [ "serde", ] -[[package]] -name = "cxx" -version = "1.0.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048948e14bc2c2652ec606c8e3bb913407f0187288fb351a0b2d972beaf12070" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-gen" -version = "0.7.122" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a476ac5d29b1957ad93669eef9a030e9fc139103f9bb1ff9f15504c3f21236b0" -dependencies = [ - "codespan-reporting", - "proc-macro2", - "quote", - "syn 2.0.49", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af40b0467c68d3d9fb7550ef984edc8ad47252f703ef0f1f2d1052e0e4af8793" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743446286141c9f6d4497c493c01234eb848e14d2e20866ae9811eae0630cb9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.49", -] - -[[package]] -name = "darling" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.49", -] - -[[package]] -name = "darling_macro" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.49", -] - [[package]] name = "dashmap" version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.3", "lock_api", "once_cell", @@ -1524,7 +1332,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -1637,26 +1444,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.49", -] - -[[package]] -name = "document-features" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" -dependencies = [ - "litrs", -] - [[package]] name = "dotenv" version = "0.15.0" @@ -1705,7 +1492,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "serde", "signature 2.2.0", ] @@ -1751,22 +1537,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ed25519-zebra" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" -dependencies = [ - "curve25519-dalek 4.1.2", - "ed25519 2.2.3", - "hashbrown 0.14.3", - "hex 0.4.3", - "rand_core 0.6.4", - "serde", - "sha2 0.10.8", - "zeroize", -] - [[package]] name = "either" version = "1.10.0" @@ -1798,7 +1568,7 @@ version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1834,16 +1604,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "equihash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" -dependencies = [ - "blake2b_simd", - "byteorder", -] - [[package]] name = "equihash" version = "0.2.0" @@ -1885,15 +1645,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "f4jumble" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" -dependencies = [ - "blake2b_simd", -] - [[package]] name = "f4jumble" version = "0.1.0" @@ -1951,18 +1702,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - [[package]] name = "fixedbitset" version = "0.4.2" @@ -2190,7 +1929,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", "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", @@ -2203,7 +1942,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -2241,25 +1980,6 @@ dependencies = [ "url", ] -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "globset" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - [[package]] name = "gloo-net" version = "0.3.1" @@ -2357,7 +2077,7 @@ dependencies = [ "indexmap 2.2.6", "slab", "tokio", - "tokio-util 0.7.11", + "tokio-util", "tracing", ] @@ -2519,12 +2239,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - [[package]] name = "hkdf" version = "0.11.0" @@ -2637,12 +2351,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "human_bytes" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f255a4535024abf7640cb288260811fc14794f62b063652ed349f9a6c2348e" - [[package]] name = "humantime" version = "1.3.0" @@ -2769,12 +2477,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.5.0" @@ -2785,26 +2487,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "incrementalmerkletree" version = "0.5.1" @@ -2866,30 +2548,14 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "integration-tests" version = "0.1.0" dependencies = [ - "hex 0.4.3", - "http", - "itertools 0.10.5", - "json", - "log", - "orchard 0.8.0", - "serde_json", - "shardtree 0.3.1", "tokio", - "zcash_address 0.3.0", - "zcash_client_backend", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", - "zingo-netutils", - "zingo-proxyd", - "zingo-rpc", - "zingoconfig", - "zingolib", "zingoproxy-testutils", ] @@ -2988,71 +2654,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" [[package]] -name = "jsonrpc-core" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" -dependencies = [ - "futures", - "futures-executor", - "futures-util", - "log", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "jsonrpc-derive" -version = "18.0.0" +name = "jubjub" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" -dependencies = [ - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "jsonrpc-http-server" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" -dependencies = [ - "futures", - "hyper", - "jsonrpc-core", - "jsonrpc-server-utils", - "log", - "net2", - "parking_lot 0.11.2", - "unicase", -] - -[[package]] -name = "jsonrpc-server-utils" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" -dependencies = [ - "bytes 1.6.0", - "futures", - "globset", - "jsonrpc-core", - "lazy_static", - "log", - "tokio", - "tokio-stream", - "tokio-util 0.6.10", - "unicase", -] - -[[package]] -name = "jubjub" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61" +checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61" dependencies = [ "bitvec", "bls12_381 0.8.0", @@ -3068,7 +2673,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "once_cell", @@ -3100,12 +2705,6 @@ dependencies = [ "spin 0.5.2", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.153" @@ -3124,16 +2723,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if 1.0.0", - "windows-targets 0.52.0", -] - [[package]] name = "libm" version = "0.2.8" @@ -3151,21 +2740,6 @@ dependencies = [ "redox_syscall 0.4.1", ] -[[package]] -name = "librocksdb-sys" -version = "0.16.0+8.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3d60bc059831dc1c83903fb45c103f75db65c5a7bf22272764d9cc683e348c" -dependencies = [ - "bindgen", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", -] - [[package]] name = "libsodium-sys" version = "0.2.7" @@ -3201,15 +2775,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "link-cplusplus" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" -dependencies = [ - "cc", -] - [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -3228,12 +2793,6 @@ dependencies = [ "keystream", ] -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - [[package]] name = "lock_api" version = "0.4.11" @@ -3287,16 +2846,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "lz4-sys" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "matchit" version = "0.7.3" @@ -3309,7 +2858,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "rayon", ] @@ -3328,38 +2877,6 @@ dependencies = [ "nonempty", ] -[[package]] -name = "metrics" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" -dependencies = [ - "ahash 0.8.8", - "metrics-macros", - "portable-atomic", -] - -[[package]] -name = "metrics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be3cbd384d4e955b231c895ce10685e3d8260c5ccffae898c96c723b0772835" -dependencies = [ - "ahash 0.8.8", - "portable-atomic", -] - -[[package]] -name = "metrics-macros" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.49", -] - [[package]] name = "mime" version = "0.3.17" @@ -3392,12 +2909,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "mset" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c4d16a3d2b0e89ec6e7d509cf791545fcb48cbc8fc2fb2e96a492defda9140" - [[package]] name = "multimap" version = "0.8.3" @@ -3422,17 +2933,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi", -] - [[package]] name = "nix" version = "0.25.1" @@ -3441,7 +2941,7 @@ checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", ] @@ -3452,7 +2952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.5.0", - "cfg-if 1.0.0", + "cfg-if", "libc", ] @@ -3596,7 +3096,7 @@ source = "git+https://github.com/nymtech/nym?branch=master#00d47958a7181d0c2ddb0 dependencies = [ "async-trait", "base64 0.21.7", - "cfg-if 1.0.0", + "cfg-if", "dashmap", "dirs 4.0.0", "futures", @@ -3976,9 +3476,9 @@ name = "nym-network-defaults" version = "0.1.0" source = "git+https://github.com/nymtech/nym?branch=master#00d47958a7181d0c2ddb0ccb01340bbe216e3b5e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dotenvy", - "hex-literal 0.3.4", + "hex-literal", "once_cell", "schemars", "serde", @@ -4009,7 +3509,7 @@ source = "git+https://github.com/nymtech/nym?branch=master#00d47958a7181d0c2ddb0 dependencies = [ "tokio", "tokio-stream", - "tokio-util 0.7.11", + "tokio-util", "wasmtimer", ] @@ -4156,7 +3656,7 @@ dependencies = [ "nym-socks5-requests", "nym-task", "tokio", - "tokio-util 0.7.11", + "tokio-util", ] [[package]] @@ -4297,7 +3797,7 @@ dependencies = [ "nym-sphinx-params", "nym-sphinx-types", "thiserror", - "tokio-util 0.7.11", + "tokio-util", ] [[package]] @@ -4485,7 +3985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" dependencies = [ "bitflags 2.5.0", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -4566,66 +4066,6 @@ dependencies = [ "zcash_note_encryption", ] -[[package]] -name = "orchard" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb255c3ffdccd3c84fe9ebed72aef64fdc72e6a3e4180dd411002d47abaad42" -dependencies = [ - "aes 0.8.4", - "bitvec", - "blake2b_simd", - "ff 0.13.0", - "fpe", - "group 0.13.0", - "halo2_gadgets", - "halo2_proofs", - "hex 0.4.3", - "incrementalmerkletree", - "lazy_static", - "memuse", - "nonempty", - "pasta_curves", - "rand 0.8.5", - "reddsa", - "serde", - "subtle 2.4.1", - "tracing", - "zcash_note_encryption", - "zcash_spec", - "zip32", -] - -[[package]] -name = "orchard" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0462569fc8b0d1b158e4d640571867a4e4319225ebee2ab6647e60c70af19ae3" -dependencies = [ - "aes 0.8.4", - "bitvec", - "blake2b_simd", - "ff 0.13.0", - "fpe", - "group 0.13.0", - "halo2_gadgets", - "halo2_proofs", - "hex 0.4.3", - "incrementalmerkletree", - "lazy_static", - "memuse", - "nonempty", - "pasta_curves", - "rand 0.8.5", - "reddsa", - "serde", - "subtle 2.4.1", - "tracing", - "zcash_note_encryption", - "zcash_spec", - "zip32", -] - [[package]] name = "ordered-float" version = "2.10.1" @@ -4635,16 +4075,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-map" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac8f4a4a06c811aa24b151dbb3fe19f687cb52e0d5cca0493671ed88f973970" -dependencies = [ - "quickcheck", - "quickcheck_macros", -] - [[package]] name = "overload" version = "0.1.1" @@ -4678,32 +4108,6 @@ dependencies = [ "group 0.13.0", ] -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -4731,7 +4135,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall 0.2.16", @@ -4745,7 +4149,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall 0.4.1", "smallvec", @@ -4968,12 +4372,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "portable-atomic" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" - [[package]] name = "portpicker" version = "0.1.1" @@ -5015,35 +4413,6 @@ dependencies = [ "syn 2.0.49", ] -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml 0.5.11", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -5163,29 +4532,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" -[[package]] -name = "quickcheck" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" -dependencies = [ - "env_logger", - "log", - "rand 0.7.3", - "rand_core 0.5.1", -] - -[[package]] -name = "quickcheck_macros" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "quote" version = "1.0.35" @@ -5549,25 +4895,6 @@ dependencies = [ "opaque-debug 0.3.0", ] -[[package]] -name = "rlimit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3560f70f30a0f16d11d01ed078a07740fe6b489667abc7c7b029155d9f21c3d8" -dependencies = [ - "libc", -] - -[[package]] -name = "rocksdb" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd13e55d6d7b8cd0ea569161127567cd587676c99f4472f779a0279aa60a7a7" -dependencies = [ - "libc", - "librocksdb-sys", -] - [[package]] name = "rust-embed" version = "6.8.1" @@ -5608,18 +4935,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - [[package]] name = "rustc_version" version = "0.4.0" @@ -5744,42 +5059,10 @@ dependencies = [ ] [[package]] -name = "sapling-crypto" -version = "0.1.3" +name = "schannel" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f4270033afcb0c74c5c7d59c73cfd1040367f67f224fe7ed9a919ae618f1b7" -dependencies = [ - "aes 0.8.4", - "bellman", - "bitvec", - "blake2b_simd", - "blake2s_simd", - "bls12_381 0.8.0", - "byteorder", - "document-features", - "ff 0.13.0", - "fpe", - "group 0.13.0", - "hex 0.4.3", - "incrementalmerkletree", - "jubjub", - "lazy_static", - "memuse", - "rand 0.8.5", - "rand_core 0.6.4", - "redjubjub", - "subtle 2.4.1", - "tracing", - "zcash_note_encryption", - "zcash_spec", - "zip32", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ "windows-sys 0.52.0", ] @@ -5856,7 +5139,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" dependencies = [ "secp256k1-sys", - "serde", ] [[package]] @@ -5933,15 +5215,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-big-array" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" -dependencies = [ - "serde", -] - [[package]] name = "serde-json-wasm" version = "0.5.0" @@ -6036,36 +5309,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex 0.4.3", - "indexmap 1.9.3", - "indexmap 2.2.6", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.49", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -6085,7 +5328,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -6097,7 +5340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -6109,7 +5352,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -6135,24 +5378,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "shardtree" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cdd24424ce0b381646737fedddc33c4dcf7dcd2d545056b53f7982097bef5" -dependencies = [ - "bitflags 2.5.0", - "either", - "incrementalmerkletree", - "tracing", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -6578,7 +5803,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "rustix", "windows-sys 0.52.0", @@ -6724,7 +5949,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -6791,7 +6016,6 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "tracing", "windows-sys 0.48.0", ] @@ -6858,18 +6082,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-socks" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" -dependencies = [ - "either", - "futures-util", - "thiserror", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -6879,7 +6091,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", - "tokio-util 0.7.11", + "tokio-util", ] [[package]] @@ -6896,20 +6108,6 @@ dependencies = [ "tungstenite", ] -[[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes 1.6.0", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.11" @@ -6942,7 +6140,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.15", + "toml_edit", ] [[package]] @@ -6967,17 +6165,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - [[package]] name = "tonic" version = "0.10.2" @@ -7037,39 +6224,12 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.11", + "tokio-util", "tower-layer", "tower-service", "tracing", ] -[[package]] -name = "tower-batch-control" -version = "0.2.41-beta.13" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "futures", - "futures-core", - "pin-project", - "rayon", - "tokio", - "tokio-util 0.7.11", - "tower", - "tracing", - "tracing-futures", -] - -[[package]] -name = "tower-fallback" -version = "0.2.41-beta.13" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "futures-core", - "pin-project", - "tower", - "tracing", -] - [[package]] name = "tower-http" version = "0.2.5" @@ -7133,26 +6293,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" -dependencies = [ - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -7272,15 +6412,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -7308,12 +6439,6 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" -[[package]] -name = "unicode-width" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" - [[package]] name = "unicode_categories" version = "0.1.1" @@ -7406,7 +6531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447f9238a4553957277b3ee09d80babeae0811f1b3baefb093de1c0448437a37" dependencies = [ "anyhow", - "cfg-if 1.0.0", + "cfg-if", "enum-iterator", "getset", "git2", @@ -7422,56 +6547,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wagyu-zcash-parameters" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c904628658374e651288f000934c33ef738b2d8b3e65d4100b70b395dbe2bb" -dependencies = [ - "wagyu-zcash-parameters-1", - "wagyu-zcash-parameters-2", - "wagyu-zcash-parameters-3", - "wagyu-zcash-parameters-4", - "wagyu-zcash-parameters-5", - "wagyu-zcash-parameters-6", -] - -[[package]] -name = "wagyu-zcash-parameters-1" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bf2e21bb027d3f8428c60d6a720b54a08bf6ce4e6f834ef8e0d38bb5695da8" - -[[package]] -name = "wagyu-zcash-parameters-2" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a616ab2e51e74cc48995d476e94de810fb16fc73815f390bf2941b046cc9ba2c" - -[[package]] -name = "wagyu-zcash-parameters-3" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14da1e2e958ff93c0830ee68e91884069253bf3462a67831b02b367be75d6147" - -[[package]] -name = "wagyu-zcash-parameters-4" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f058aeef03a2070e8666ffb5d1057d8bb10313b204a254a6e6103eb958e9a6d6" - -[[package]] -name = "wagyu-zcash-parameters-5" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffe916b30e608c032ae1b734f02574a3e12ec19ab5cc5562208d679efe4969d" - -[[package]] -name = "wagyu-zcash-parameters-6" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b6d5a78adc3e8f198e9cd730f219a695431467f7ec29dcfc63ade885feebe1" - [[package]] name = "wait-timeout" version = "0.2.0" @@ -7512,13 +6587,19 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -7543,7 +6624,7 @@ version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -7674,6 +6755,17 @@ dependencies = [ "rustix", ] +[[package]] +name = "whoami" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +dependencies = [ + "redox_syscall 0.4.1", + "wasite", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -7861,7 +6953,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -7910,21 +7002,8 @@ source = "git+https://github.com/zingolabs/librustzcash.git?branch=nym_integrati dependencies = [ "bech32", "bs58 0.5.1", - "f4jumble 0.1.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", -] - -[[package]] -name = "zcash_address" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827c17a1f7e3a69f0d44e991ff610c7a842228afdc9dc2325ffdd1a67fee01e9" -dependencies = [ - "bech32", - "bs58 0.5.1", - "f4jumble 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_protocol", + "f4jumble", + "zcash_encoding", ] [[package]] @@ -7944,32 +7023,22 @@ dependencies = [ "incrementalmerkletree", "memuse", "nom", - "orchard 0.6.0", + "orchard", "percent-encoding", "prost", "rayon", "secrecy", - "shardtree 0.1.0", + "shardtree", "subtle 2.4.1", "time", "tonic", "tonic-build", "tracing", "which", - "zcash_address 0.3.0", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", -] - -[[package]] -name = "zcash_encoding" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03391b81727875efa6ac0661a20883022b6fba92365dc121c48fa9b00c5aac0" -dependencies = [ - "byteorder", - "nonempty", + "zcash_primitives", ] [[package]] @@ -7981,17 +7050,6 @@ dependencies = [ "nonempty", ] -[[package]] -name = "zcash_history" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fde17bf53792f9c756b313730da14880257d7661b5bfc69d0571c3a7c11a76d" -dependencies = [ - "blake2b_simd", - "byteorder", - "primitive-types", -] - [[package]] name = "zcash_note_encryption" version = "0.4.0" @@ -8005,42 +7063,6 @@ dependencies = [ "subtle 2.4.1", ] -[[package]] -name = "zcash_primitives" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17e4c94ca8d69d2fcf2be97522da5732a580eb2125cda3b150761952f8df8e6" -dependencies = [ - "aes 0.8.4", - "bip0039", - "bitvec", - "blake2b_simd", - "blake2s_simd", - "bls12_381 0.8.0", - "byteorder", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.13.0", - "fpe", - "group 0.13.0", - "hdwallet", - "hex 0.4.3", - "incrementalmerkletree", - "jubjub", - "lazy_static", - "memuse", - "nonempty", - "orchard 0.6.0", - "rand 0.8.5", - "rand_core 0.6.4", - "ripemd", - "secp256k1", - "sha2 0.10.8", - "subtle 2.4.1", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_note_encryption", -] - [[package]] name = "zcash_primitives" version = "0.13.0" @@ -8054,7 +7076,7 @@ dependencies = [ "blake2s_simd", "bls12_381 0.8.0", "byteorder", - "equihash 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "equihash", "ff 0.13.0", "fpe", "group 0.13.0", @@ -8065,75 +7087,16 @@ dependencies = [ "lazy_static", "memuse", "nonempty", - "orchard 0.6.0", - "rand 0.8.5", - "rand_core 0.6.4", - "ripemd", - "secp256k1", - "sha2 0.10.8", - "subtle 2.4.1", - "zcash_address 0.3.0", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", - "zcash_note_encryption", -] - -[[package]] -name = "zcash_primitives" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9070e084570bb78aed4f8d71fd6254492e62c87a5d01e084183980e98117092d" -dependencies = [ - "aes 0.8.4", - "bip0039", - "blake2b_simd", - "byteorder", - "document-features", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.13.0", - "fpe", - "group 0.13.0", - "hdwallet", - "hex 0.4.3", - "incrementalmerkletree", - "jubjub", - "memuse", - "nonempty", - "orchard 0.7.1", + "orchard", "rand 0.8.5", "rand_core 0.6.4", - "redjubjub", "ripemd", - "sapling-crypto", "secp256k1", "sha2 0.10.8", "subtle 2.4.1", - "tracing", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", - "zcash_spec", - "zip32", -] - -[[package]] -name = "zcash_proofs" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0c99f65a840ff256c106b28d67d702d9759d206112473d4982c92003262406" -dependencies = [ - "bellman", - "blake2b_simd", - "bls12_381 0.8.0", - "group 0.13.0", - "home", - "jubjub", - "known-folders", - "lazy_static", - "rand_core 0.6.4", - "redjubjub", - "tracing", - "xdg", - "zcash_primitives 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -8153,291 +7116,7 @@ dependencies = [ "redjubjub", "tracing", "xdg", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", -] - -[[package]] -name = "zcash_proofs" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a02eb1f151d9b9a6e16408d2c55ff440bd2fb232b7377277146d0fa2df9bc8" -dependencies = [ - "bellman", - "blake2b_simd", - "bls12_381 0.8.0", - "document-features", - "group 0.13.0", - "home", - "jubjub", - "known-folders", - "lazy_static", - "rand_core 0.6.4", - "redjubjub", - "sapling-crypto", - "tracing", - "xdg", - "zcash_primitives 0.14.0", -] - -[[package]] -name = "zcash_protocol" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8189d4a304e8aa3aef3b75e89f3874bb0dc84b1cd623316a84e79e06cddabc" -dependencies = [ - "document-features", - "memuse", -] - -[[package]] -name = "zcash_script" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3febfe5f2abdab3597d17c8f71cc0071902d82f8433aa329abe52461eabaa9c4" -dependencies = [ - "bellman", - "bindgen", - "blake2b_simd", - "blake2s_simd", - "bls12_381 0.8.0", - "bridgetree", - "byteorder", - "cc", - "crossbeam-channel", - "cxx", - "cxx-gen", - "group 0.13.0", - "incrementalmerkletree", - "jubjub", - "libc", - "memuse", - "metrics 0.21.1", - "orchard 0.7.1", - "rand 0.8.5", - "rand_core 0.6.4", - "rayon", - "redjubjub", - "sapling-crypto", - "subtle 2.4.1", - "syn 1.0.109", - "tracing", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_note_encryption", - "zcash_primitives 0.14.0", - "zcash_proofs 0.14.0", -] - -[[package]] -name = "zcash_spec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b" -dependencies = [ - "blake2b_simd", -] - -[[package]] -name = "zebra-chain" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "bitflags 2.5.0", - "bitflags-serde-legacy", - "bitvec", - "blake2b_simd", - "blake2s_simd", - "bridgetree", - "bs58 0.5.1", - "byteorder", - "chrono", - "displaydoc", - "ed25519-zebra 4.0.3", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures", - "group 0.13.0", - "halo2_proofs", - "hex 0.4.3", - "humantime 2.1.0", - "incrementalmerkletree", - "itertools 0.12.1", - "jubjub", - "lazy_static", - "num-integer", - "orchard 0.6.0", - "primitive-types", - "rand_core 0.6.4", - "rayon", - "reddsa", - "redjubjub", - "ripemd", - "secp256k1", - "serde", - "serde-big-array", - "serde_json", - "serde_with", - "sha2 0.10.8", - "static_assertions", - "thiserror", - "tokio", - "tracing", - "uint", - "x25519-dalek 2.0.1", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_history", - "zcash_note_encryption", - "zcash_primitives 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_protocol", -] - -[[package]] -name = "zebra-consensus" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "bellman", - "blake2b_simd", - "bls12_381 0.8.0", - "chrono", - "displaydoc", - "futures", - "futures-util", - "halo2_proofs", - "jubjub", - "lazy_static", - "metrics 0.22.3", - "once_cell", - "orchard 0.6.0", - "rand 0.8.5", - "rayon", - "serde", - "thiserror", - "tokio", - "tower", - "tower-batch-control", - "tower-fallback", - "tracing", - "tracing-futures", - "wagyu-zcash-parameters", - "zcash_proofs 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zebra-chain", - "zebra-node-services", - "zebra-script", - "zebra-state", -] - -[[package]] -name = "zebra-network" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "bitflags 2.5.0", - "byteorder", - "bytes 1.6.0", - "chrono", - "dirs 5.0.1", - "futures", - "hex 0.4.3", - "humantime-serde", - "indexmap 2.2.6", - "itertools 0.12.1", - "lazy_static", - "metrics 0.22.3", - "num-integer", - "ordered-map", - "pin-project", - "rand 0.8.5", - "rayon", - "regex", - "serde", - "tempfile", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util 0.7.11", - "tower", - "tracing", - "tracing-error", - "tracing-futures", - "zebra-chain", -] - -[[package]] -name = "zebra-node-services" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "zebra-chain", -] - -[[package]] -name = "zebra-rpc" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "chrono", - "futures", - "hex 0.4.3", - "hyper", - "indexmap 2.2.6", - "jsonrpc-core", - "jsonrpc-derive", - "jsonrpc-http-server", - "serde", - "serde_json", - "tokio", - "tower", - "tracing", - "zebra-chain", - "zebra-consensus", - "zebra-network", - "zebra-node-services", - "zebra-script", - "zebra-state", -] - -[[package]] -name = "zebra-script" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "displaydoc", - "thiserror", - "zcash_script", - "zebra-chain", -] - -[[package]] -name = "zebra-state" -version = "1.0.0-beta.37" -source = "git+https://github.com/ZcashFoundation/zebra.git#0f5450f5650102aea1fff43ec88c065ef1976e79" -dependencies = [ - "bincode", - "chrono", - "dirs 5.0.1", - "futures", - "hex 0.4.3", - "hex-literal 0.4.1", - "human_bytes", - "humantime-serde", - "indexmap 2.2.6", - "itertools 0.12.1", - "lazy_static", - "metrics 0.22.3", - "mset", - "rayon", - "regex", - "rlimit", - "rocksdb", - "semver 1.0.23", - "serde", - "tempfile", - "thiserror", - "tokio", - "tower", - "tracing", - "zebra-chain", + "zcash_primitives", ] [[package]] @@ -8485,11 +7164,11 @@ name = "zingo-memo" version = "0.1.0" source = "git+https://github.com/zingolabs/zingolib.git?branch=nym_integration#f5eeb37c04d7b1b58f8c6189291ce73349cec471" dependencies = [ - "zcash_address 0.3.0", + "zcash_address", "zcash_client_backend", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_encoding", "zcash_note_encryption", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_primitives", ] [[package]] @@ -8514,25 +7193,13 @@ dependencies = [ name = "zingo-proxyd" version = "0.1.0" dependencies = [ - "bytes 1.6.0", "ctrlc", "http", - "http-body", - "hyper", - "hyper-rustls 0.23.2", "nym-bin-common", "nym-sdk", - "nym-sphinx-addressing", "nym-sphinx-anonymous-replies", - "nym-validator-client", - "prost", - "rustls-pemfile", "tokio", - "tokio-rustls 0.23.4", - "tokio-socks", "tonic", - "tower", - "webpki-roots 0.21.1", "zcash_client_backend", "zingo-netutils", "zingo-rpc", @@ -8550,32 +7217,24 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls 0.23.2", "hyper-tls", "indexmap 2.2.6", - "jsonrpc-core", - "nym-bin-common", "nym-sdk", "nym-sphinx-addressing", "nym-sphinx-anonymous-replies", - "nym-validator-client", "prost", - "rustls-pemfile", "serde", "serde_json", "sha2 0.10.8", "thiserror", "tokio", - "tokio-rustls 0.23.4", "tokio-stream", "tonic", + "tonic-build", "tower", - "webpki-roots 0.21.1", + "which", + "whoami", "zcash_client_backend", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", - "zebra-chain", - "zebra-rpc", - "zebra-state", "zingo-netutils", ] @@ -8585,7 +7244,7 @@ version = "0.1.0" source = "git+https://github.com/zingolabs/zingolib.git?branch=nym_integration#f5eeb37c04d7b1b58f8c6189291ce73349cec471" dependencies = [ "serde_json", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_primitives", ] [[package]] @@ -8598,7 +7257,7 @@ dependencies = [ "incrementalmerkletree", "json", "log", - "orchard 0.6.0", + "orchard", "portpicker", "serde", "serde_json", @@ -8607,9 +7266,9 @@ dependencies = [ "tonic", "tonic-build", "tracing", - "zcash_address 0.3.0", + "zcash_address", "zcash_client_backend", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_primitives", "zingo-netutils", "zingoconfig", "zingolib", @@ -8620,7 +7279,7 @@ name = "zingo-testvectors" version = "0.1.0" source = "git+https://github.com/zingolabs/zingolib.git?branch=nym_integration#f5eeb37c04d7b1b58f8c6189291ce73349cec471" dependencies = [ - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_primitives", "zingoconfig", ] @@ -8633,8 +7292,8 @@ dependencies = [ "http", "log", "log4rs", - "zcash_address 0.3.0", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_address", + "zcash_primitives", ] [[package]] @@ -8668,7 +7327,7 @@ dependencies = [ "log", "log4rs", "nonempty", - "orchard 0.6.0", + "orchard", "pairing 0.23.0", "prost", "rand 0.8.5", @@ -8680,7 +7339,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.9.9", - "shardtree 0.1.0", + "shardtree", "sodiumoxide", "subtle 2.4.1", "tokio", @@ -8692,12 +7351,12 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", - "zcash_address 0.3.0", + "zcash_address", "zcash_client_backend", - "zcash_encoding 0.2.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_encoding", "zcash_note_encryption", - "zcash_primitives 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", - "zcash_proofs 0.13.0 (git+https://github.com/zingolabs/librustzcash.git?branch=nym_integration)", + "zcash_primitives", + "zcash_proofs", "zingo-memo", "zingo-netutils", "zingo-status", @@ -8709,29 +7368,15 @@ dependencies = [ name = "zingoproxy-testutils" version = "0.1.0" dependencies = [ - "chrono", "ctrlc", "http", - "nym-sdk", "portpicker", "tempfile", "tokio", "tonic", - "zcash_client_backend", "zingo-proxyd", "zingo-rpc", "zingo-testutils", "zingoconfig", "zingolib", ] - -[[package]] -name = "zip32" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" -dependencies = [ - "blake2b_simd", - "memuse", - "subtle 2.4.1", -] diff --git a/Cargo.toml b/Cargo.toml index 1449c3c..b4b991c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,26 +9,31 @@ members = [ # Use the edition 2021 dependency resolver in the workspace, to match the crates resolver = "2" -[workspace.dependencies] -zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration", features = ["lightwalletd-tonic"] } -# TODO: Change dependency to stable once net-utils merges. -zingo-netutils = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration" } +[workspace.package] +authors = ["Zingolabs Viridian"] +repository = "https://github.com/zingolabs" +homepage = "https://www.zingolabs.org/" +edition = "2021" +license = "Apache-2.0" + +[workspace.dependencies] +# NymSdk nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" } nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", branch = "master" } -nym-validator-client = { git = "https://github.com/nymtech/nym", branch = "master" } nym-bin-common = { git = "https://github.com/nymtech/nym", branch = "master" } nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", branch = "master" } +# nym-sdk = { git = "https://github.com/nymtech/nym", tag = "nym-binaries-v2024.7-doubledecker" } +# nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", tag = "nym-binaries-v2024.7-doubledecker" } +# nym-bin-common = { git = "https://github.com/nymtech/nym", tag = "nym-binaries-v2024.7-doubledecker" } +# nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", tag = "nym-binaries-v2024.7-doubledecker" } -http = "0.2.4" -tokio = { version = "1.37.0", features = ["full"] } -tonic = "0.10.2" -prost = "0.12" -bytes = "1.1" -http-body = "0.4.4" -hyper = { version = "0.14.28", features = ["full"] } -hyper-rustls = { version = "0.23", features = ["http2"] } -tower = { version = "0.4.13" } -tokio-rustls = "0.23" -rustls-pemfile = "1.0.0" +# Miscellaneous +tokio = { version = "1.37.0", features = ["full"] } # { version = "1.38.1", features = ["full"] } +tonic = "0.10.2" # "0.12" +http = "0.2.4" # "1.1" +thiserror = "1.0.59" # "1.0.62" +# [patch.crates-io] +# incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "337f59179eda51261e9ddfc6b18e8fb84ea277c9" } +# shardtree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "337f59179eda51261e9ddfc6b18e8fb84ea277c9" } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index d8c871c..8fc2e0a 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,37 +1,19 @@ [package] name = "integration-tests" version = "0.1.0" -authors = ["zingo@zingolabs.org"] -edition = "2021" +description = "Crate containing Zingo-Proxy 'Wallet-to-Node' tests." +edition = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +repository = { workspace = true } [features] -nym = [] # NOTE: Deprecated nym_poc = [] [dependencies] zingoproxy-testutils = { path = "../zingoproxy-testutils" } -zingo-proxyd = { path = "../zingo-proxyd" } -zingo-rpc = { path = "../zingo-rpc" } - -zcash_client_backend = { workspace = true } -zingo-netutils = { workspace = true } +# Miscellaneous Workspace tokio = { workspace = true } -http = { workspace = true } - -# TODO: Change dependency to stable once net-utils merges. -zingolib = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration", features = ["test-features"] } -zingoconfig = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration" } - -zcash_primitives = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration" } -zcash_address = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration" } -orchard = "0.8" -shardtree = "0.3" - -json = "0.12.4" -log = "0.4.17" -itertools = "0.10.5" -serde_json = "1.0.117" -hex = "0.4" diff --git a/integration-tests/tests/integrations.rs b/integration-tests/tests/integrations.rs index 3a16758..068fbfc 100644 --- a/integration-tests/tests/integrations.rs +++ b/integration-tests/tests/integrations.rs @@ -4,9 +4,9 @@ #![forbid(unsafe_code)] use std::sync::{atomic::AtomicBool, Arc}; -use zingo_netutils::GrpcConnector; -use zingolib::lightclient::LightClient; -use zingoproxy_testutils::{drop_test_manager, TestManager}; +use zingoproxy_testutils::{ + drop_test_manager, get_zingo_address, start_zingo_mempool_monitor, ProxyPool, TestManager, +}; mod wallet_basic { use super::*; @@ -16,24 +16,14 @@ mod wallet_basic { let online = Arc::new(AtomicBool::new(true)); let (test_manager, regtest_handler, _proxy_handler) = TestManager::launch(online.clone()).await; + let zingo_client = test_manager.build_lightclient().await; - println!( - "@zingoproxytest: Attempting to connect to GRPC server at URI: {}.", - test_manager.get_proxy_uri() - ); - let mut client = GrpcConnector::new(test_manager.get_proxy_uri()) - .get_client() - .await - .expect("Failed to create GRPC client"); - let lightd_info = client - .get_lightd_info(zcash_client_backend::proto::service::Empty {}) - .await - .expect("Failed to retrieve lightd info from GRPC server"); - + let lightd_info = zingo_client.do_info().await; println!( "@zingoproxytest: Lightd_info response:\n{:#?}.", - lightd_info.into_inner() + lightd_info ); + drop_test_manager( Some(test_manager.temp_conf_dir.path().to_path_buf()), regtest_handler, @@ -53,7 +43,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "unified"), + &get_zingo_address(&zingo_client, "unified").await, 250_000, None, )]) @@ -85,7 +75,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -117,7 +107,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "transparent"), + &get_zingo_address(&zingo_client, "transparent").await, 250_000, None, )]) @@ -149,7 +139,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "unified"), + &get_zingo_address(&zingo_client, "unified").await, 250_000, None, )]) @@ -157,7 +147,7 @@ mod wallet_basic { .unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -165,7 +155,7 @@ mod wallet_basic { .unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "transparent"), + &get_zingo_address(&zingo_client, "transparent").await, 250_000, None, )]) @@ -199,7 +189,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -213,13 +203,7 @@ mod wallet_basic { assert_eq!(balance.sapling_balance.unwrap(), 250_000); zingo_client - .do_shield( - &[ - zingolib::wallet::Pool::Sapling, - // zingolib::wallet::Pool::Transparent, - ], - None, - ) + .do_shield(&[ProxyPool::Sapling.into()], None) .await .unwrap(); test_manager.regtest_manager.generate_n_blocks(1).unwrap(); @@ -249,7 +233,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "transparent"), + &get_zingo_address(&zingo_client, "transparent").await, 250_000, None, )]) @@ -263,13 +247,7 @@ mod wallet_basic { assert_eq!(balance.transparent_balance.unwrap(), 250_000); zingo_client - .do_shield( - &[ - // zingolib::wallet::Pool::Sapling, - zingolib::wallet::Pool::Transparent, - ], - None, - ) + .do_shield(&[ProxyPool::Transparent.into()], None) .await .unwrap(); test_manager.regtest_manager.generate_n_blocks(1).unwrap(); @@ -299,7 +277,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -307,7 +285,7 @@ mod wallet_basic { .unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "transparent"), + &get_zingo_address(&zingo_client, "transparent").await, 250_000, None, )]) @@ -323,10 +301,7 @@ mod wallet_basic { zingo_client .do_shield( - &[ - zingolib::wallet::Pool::Sapling, - zingolib::wallet::Pool::Transparent, - ], + &[ProxyPool::Sapling.into(), ProxyPool::Transparent.into()], None, ) .await @@ -361,7 +336,7 @@ mod wallet_basic { test_manager.regtest_manager.generate_n_blocks(30).unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "unified"), + &get_zingo_address(&zingo_client, "unified").await, 250_000, None, )]) @@ -370,7 +345,7 @@ mod wallet_basic { test_manager.regtest_manager.generate_n_blocks(30).unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -379,13 +354,15 @@ mod wallet_basic { test_manager.regtest_manager.generate_n_blocks(30).unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "transparent"), + &get_zingo_address(&zingo_client, "transparent").await, 250_000, None, )]) .await .unwrap(); test_manager.regtest_manager.generate_n_blocks(30).unwrap(); + + println!("@zingoproxytest: syncing full batch."); zingo_client.do_sync(false).await.unwrap(); let balance = zingo_client.do_balance().await; @@ -413,7 +390,7 @@ mod wallet_basic { zingo_client.do_sync(false).await.unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) @@ -421,25 +398,14 @@ mod wallet_basic { .unwrap(); zingo_client .do_send(vec![( - &zingolib::get_base_address!(zingo_client, "sapling"), + &get_zingo_address(&zingo_client, "sapling").await, 250_000, None, )]) .await .unwrap(); - let zingo_client_saved = zingo_client.export_save_buffer_async().await.unwrap(); - let zingo_client_loaded = std::sync::Arc::new( - LightClient::read_wallet_from_buffer_async( - zingo_client.config(), - &zingo_client_saved[..], - ) - .await - .unwrap(), - ); - LightClient::start_mempool_monitor(zingo_client_loaded.clone()); - // This seems to be long enough for the mempool monitor to kick in. - tokio::time::sleep(std::time::Duration::from_secs(5)).await; + start_zingo_mempool_monitor(&zingo_client).await; let balance = zingo_client.do_balance().await; println!("@zingoproxytest: zingo_client balance: \n{:#?}.", balance); @@ -463,7 +429,3 @@ mod wallet_basic { mod nym { // TODO: Build nym enhanced zingolib version using zingo-rpc::walletrpc::service. } - -mod darkside { - // TODO: Add darkside. -} diff --git a/zingo-proxyd/Cargo.toml b/zingo-proxyd/Cargo.toml index 2838ec3..385250c 100644 --- a/zingo-proxyd/Cargo.toml +++ b/zingo-proxyd/Cargo.toml @@ -1,8 +1,11 @@ [package] name = "zingo-proxyd" version = "0.1.0" -authors = ["zingo@zingolabs.org"] -edition = "2021" +description = "Crate containing the Zingo-Proxy LightWallet server binary." +edition = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +repository = { workspace = true } [[bin]] name = "zingoproxyd" @@ -13,36 +16,29 @@ name = "zingoproxylib" path = "src/lib.rs" [features] -# TODO: Add [default = [ "nym" ]] when nym poc is removed, or remove "nym" all together. -nym = [] # NOTE: Deprecated -nym_poc = [] +nym_poc = ["zingo-netutils", "zcash_client_backend"] [dependencies] -zingo-rpc = { path = "../zingo-rpc" } +# Zinglib and LibRustZcash: +# +# Only used in original nym_poc code, to be removed with creation of nym enhanced zingolib build. +# +# Not to be used in production code as zingo-rpc will become a dep of zingolib and zingo-proxy now builds its onw CompactTxStreamer. +zingo-netutils = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration", optional = true } +zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration", features = ["lightwalletd-tonic"], optional = true } -zcash_client_backend = { workspace = true, features = ["lightwalletd-tonic"] } -zingo-netutils = { workspace = true } +zingo-rpc = { path = "../zingo-rpc" } +# NymSdk nym-sdk = { workspace = true } -nym-sphinx-addressing = { workspace = true } -nym-validator-client = { workspace = true } nym-bin-common = { workspace = true } nym-sphinx-anonymous-replies = { workspace = true } -http = { workspace = true } +# Miscellaneous Workspace tokio = { workspace = true, features = ["full"] } tonic = { workspace = true } -prost = { workspace = true } -bytes = { workspace = true } -http-body = { workspace = true } -tower = { workspace = true } -hyper-rustls = { workspace = true, features = ["http2"] } -hyper = { workspace = true, features = ["full"] } -tokio-rustls = { workspace = true } -rustls-pemfile = { workspace = true } - -tokio-socks = "0.5" -ctrlc = "3.2.1" -webpki-roots = "0.21.0" +http = { workspace = true } +# Miscellaneous Crate +ctrlc = "3.2.1" # "3.4.4" diff --git a/zingo-proxyd/src/nym_server.rs b/zingo-proxyd/src/nym_server.rs index 29c036f..6b8c92c 100644 --- a/zingo-proxyd/src/nym_server.rs +++ b/zingo-proxyd/src/nym_server.rs @@ -11,12 +11,9 @@ use std::sync::{ use nym_sdk::mixnet::{MixnetMessageSender, ReconstructedMessage}; use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag; -// use prost::Message; -// use zcash_client_backend::proto::service::RawTransaction; use zingo_rpc::{ - jsonrpc::connector::test_node_and_return_uri, - primitives::{NymClient, ProxyClient}, + primitives::client::{NymClient, ProxyClient}, queue::request::ZingoProxyRequest, }; @@ -41,7 +38,6 @@ impl NymServer { // NOTE: the following should be removed with the addition of the queue and worker pool. let lwd_port = 8080; let zebrad_port = 18232; - println!("@zingoproxyd[nym]: Launching temporary proxy client.."); let proxy_client = ProxyClient { lightwalletd_uri: http::Uri::builder() .scheme("http") @@ -55,13 +51,6 @@ impl NymServer { .path_and_query("/") .build() .unwrap(), - // zebrad_uri: test_node_and_return_uri( - // &zebrad_port, - // Some("xxxxxx".to_string()), - // Some("xxxxxx".to_string()), - // ) - // .await - // .unwrap(), online: self.online.clone(), }; while self.online.load(Ordering::SeqCst) { @@ -92,7 +81,8 @@ impl NymServer { .unwrap(); // --- build ZingoProxyRequest let zingo_proxy_request = - ZingoProxyRequest::new_from_nym(return_recipient, request_vu8.as_ref()); + ZingoProxyRequest::new_from_nym(return_recipient, request_vu8.as_ref()) + .unwrap(); // print request for testing // println!( @@ -128,7 +118,7 @@ impl NymServer { /// Returns a new NymServer Inatanse pub async fn new(nym_conf_path: &str, online: Arc) -> Self { - let nym_client = NymClient::nym_spawn(nym_conf_path).await; + let nym_client = NymClient::nym_spawn(nym_conf_path).await.unwrap(); let nym_addr = nym_client.0.nym_address().to_string(); NymServer { nym_client, diff --git a/zingo-proxyd/src/proxy.rs b/zingo-proxyd/src/proxy.rs index 7235f7a..2b07d37 100644 --- a/zingo-proxyd/src/proxy.rs +++ b/zingo-proxyd/src/proxy.rs @@ -4,8 +4,10 @@ //! - Update spawn_server and nym_spawn to return > and > and use here. use crate::{nym_server::NymServer, server::spawn_grpc_server}; -use zcash_client_backend::proto::service::compact_tx_streamer_client::CompactTxStreamerClient; -use zingo_rpc::jsonrpc::connector::test_node_and_return_uri; +use zingo_rpc::{ + jsonrpc::connector::test_node_and_return_uri, + proto::service::{compact_tx_streamer_client::CompactTxStreamerClient, Empty}, +}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -90,12 +92,7 @@ async fn wait_on_grpc_startup(proxy_port: &u16, online: Arc) { interval.tick().await; while attempts < 3 { match CompactTxStreamerClient::connect(proxy_uri.clone()).await { - Ok(mut client) => match client - .get_lightd_info(tonic::Request::new( - zcash_client_backend::proto::service::Empty {}, - )) - .await - { + Ok(mut client) => match client.get_lightd_info(tonic::Request::new(Empty {})).await { Ok(_) => { return; } diff --git a/zingo-proxyd/src/server.rs b/zingo-proxyd/src/server.rs index d4598bf..17ed5ca 100644 --- a/zingo-proxyd/src/server.rs +++ b/zingo-proxyd/src/server.rs @@ -3,6 +3,7 @@ //! TODO: - Add GrpcServerError error type and rewrite functions to return >, propagating internal errors. //! - Add user and password as fields of ProxyClient and use here. +use http::Uri; use std::{ net::{Ipv4Addr, SocketAddr}, sync::{ @@ -10,10 +11,13 @@ use std::{ Arc, }, }; +use zingo_rpc::{jsonrpc::connector::test_node_and_return_uri, primitives::client::ProxyClient}; -use http::Uri; +#[cfg(not(feature = "nym_poc"))] +use zingo_rpc::proto::service::compact_tx_streamer_server::CompactTxStreamerServer; + +#[cfg(feature = "nym_poc")] use zcash_client_backend::proto::service::compact_tx_streamer_server::CompactTxStreamerServer; -use zingo_rpc::{jsonrpc::connector::test_node_and_return_uri, primitives::ProxyClient}; /// Configuration data for gRPC server. pub struct ProxyServer(pub ProxyClient); diff --git a/zingo-rpc/Cargo.toml b/zingo-rpc/Cargo.toml index d39dc86..be83311 100644 --- a/zingo-rpc/Cargo.toml +++ b/zingo-rpc/Cargo.toml @@ -1,56 +1,54 @@ [package] name = "zingo-rpc" version = "0.1.0" -authors = ["zingo@zingolabs.org"] -edition = "2021" -build = "build.rs" +description = "Crate containing the Zingo-Proxy LightWallet server library." +edition = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +repository = { workspace = true } [features] -test = [] # NOTE: Deprecated -nym_poc = [] +nym_poc = ["zingo-netutils", "zcash_client_backend"] [dependencies] -zebra-rpc = { git = "https://github.com/ZcashFoundation/zebra.git" } -zebra-chain = { git = "https://github.com/ZcashFoundation/zebra.git" } -zebra-state = { git = "https://github.com/ZcashFoundation/zebra.git" } - -zcash_client_backend = { workspace = true, features = ["lightwalletd-tonic"] } -zingo-netutils = { workspace = true } -zcash_encoding = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration" } - +# Zinglib and LibRustZcash: +# +# Only used in original nym_poc code, to be removed with creation of nym enhanced zingolib build. +# +# Not to be used in production code as zingo-rpc will become a dep of zingolib and zingo-proxy now builds its onw CompactTxStreamer. +zingo-netutils = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration", optional = true } +zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash.git", branch = "nym_integration", features = ["lightwalletd-tonic"], optional = true } + +# NymSdk nym-sdk = { workspace = true } nym-sphinx-addressing = { workspace = true } -nym-validator-client = { workspace = true } -nym-bin-common = { workspace = true } nym-sphinx-anonymous-replies = { workspace = true } -http = { workspace = true } +# Miscellaneous Workspace tokio = { workspace = true, features = ["full"] } tonic = { workspace = true } -prost = { workspace = true } -bytes = { workspace = true } -http-body = { workspace = true } -tower = { workspace = true } -hyper-rustls = { workspace = true, features = ["http2"] } -hyper = { workspace = true, features = ["full"] } -tokio-rustls = { workspace = true } -rustls-pemfile = { workspace = true } - -webpki-roots = "0.21.0" -serde = { version = "1.0.201", features = ["derive"] } -hyper-tls = "0.5" +http = { workspace = true } +thiserror = { workspace = true } + +# Miscellaneous Crate +prost = "0.12" # "0.13.1" +bytes = "1.1" # "1.6.1" +http-body = "0.4.4" # "1.0.1" +tower = { version = "0.4.13" } +hyper = { version = "0.14.28", features = ["full"] } # { version = "1.4.1", features = ["full"] } +serde_json = { version = "1.0.117", features = ["preserve_order"] } # { version = "1.0.120", features = ["preserve_order"] } # The preserve_order feature in serde_jsonn is a dependency of jsonrpc-core +serde = { version = "1.0.201", features = ["derive"] } # { version = "1.0.204", features = ["derive"] } +hyper-tls = "0.5" # "0.6" hex = { version = "0.4.3", features = ["serde"] } - -# The preserve_order feature in serde_jsonn is a dependency of jsonrpc-core -serde_json = { version = "1.0.117", features = ["preserve_order"] } -jsonrpc-core = "18.0.0" - indexmap = { version = "2.2.6", features = ["serde"] } -base64 = "0.13.0" -tokio-stream = "0.1" +base64 = "0.13.0" # "0.22.1" +tokio-stream = "0.1" # "0.1.15" futures = "0.3.30" -byteorder = "1" -sha2 = "0.10" -thiserror = "1.0.59" +byteorder = "1" # "1.5" +sha2 = "0.10" # "0.10.8" +[build-dependencies] +tonic-build = { version = "0.10", features = ["prost"] } # "0.12" +which = "4" +whoami = "1.0" # "1.5" diff --git a/zingo-rpc/build.rs b/zingo-rpc/build.rs index bc2cb1f..63e43b8 100644 --- a/zingo-rpc/build.rs +++ b/zingo-rpc/build.rs @@ -1,7 +1,14 @@ use std::env; +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; use std::process::Command; -fn main() { +const COMPACT_FORMATS_PROTO: &str = "proto/compact_formats.proto"; +const PROPOSAL_PROTO: &str = "proto/proposal.proto"; +const SERVICE_PROTO: &str = "proto/service.proto"; + +fn main() -> io::Result<()> { // Fetch the commit hash let commit_hash = Command::new("git") .args(["rev-parse", "HEAD"]) @@ -29,10 +36,86 @@ fn main() { println!("cargo:rustc-env=BUILD_DATE={}", build_date.trim()); // Set the build user - let build_user = env::var("USER").expect("Failed to get build user"); + let build_user = whoami::username(); println!("cargo:rustc-env=BUILD_USER={}", build_user); // Set the version from Cargo.toml let version = env::var("CARGO_PKG_VERSION").expect("Failed to get version from Cargo.toml"); println!("cargo:rustc-env=VERSION={}", version); + + // Check and compile proto files if needed + if Path::new(COMPACT_FORMATS_PROTO).exists() + && env::var_os("PROTOC") + .map(PathBuf::from) + .or_else(|| which::which("protoc").ok()) + .is_some() + { + build()?; + } + + Ok(()) +} + +fn build() -> io::Result<()> { + let out: PathBuf = env::var_os("OUT_DIR") + .expect("Cannot find OUT_DIR environment variable") + .into(); + + // Build the compact format types. + tonic_build::compile_protos(COMPACT_FORMATS_PROTO)?; + + // Copy the generated types into the source tree so changes can be committed. + fs::copy( + out.join("cash.z.wallet.sdk.rpc.rs"), + "src/proto/compact_formats.rs", + )?; + + // Build the gRPC types and client. + tonic_build::configure() + .build_server(true) + // .client_mod_attribute( + // "cash.z.wallet.sdk.rpc", + // r#"#[cfg(feature = "lightwalletd-tonic")]"#, + // ) + .extern_path( + ".cash.z.wallet.sdk.rpc.ChainMetadata", + "crate::proto::compact_formats::ChainMetadata", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactBlock", + "crate::proto::compact_formats::CompactBlock", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactTx", + "crate::proto::compact_formats::CompactTx", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactSaplingSpend", + "crate::proto::compact_formats::CompactSaplingSpend", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactSaplingOutput", + "crate::proto::compact_formats::CompactSaplingOutput", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactOrchardAction", + "crate::proto::compact_formats::CompactOrchardAction", + ) + .compile(&[SERVICE_PROTO], &["proto/"])?; + + // Build the proposal types. + tonic_build::compile_protos(PROPOSAL_PROTO)?; + + // Copy the generated types into the source tree so changes can be committed. + fs::copy( + out.join("cash.z.wallet.sdk.ffi.rs"), + "src/proto/proposal.rs", + )?; + + // Copy the generated types into the source tree so changes can be committed. The + // file has the same name as for the compact format types because they have the + // same package, but we've set things up so this only contains the service types. + fs::copy(out.join("cash.z.wallet.sdk.rpc.rs"), "src/proto/service.rs")?; + + Ok(()) } diff --git a/zingo-rpc/proto/compact_formats.proto b/zingo-rpc/proto/compact_formats.proto new file mode 100644 index 0000000..e39e522 --- /dev/null +++ b/zingo-rpc/proto/compact_formats.proto @@ -0,0 +1,84 @@ +// Copyright (c) 2019-2021 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +syntax = "proto3"; +package cash.z.wallet.sdk.rpc; +option go_package = "walletrpc"; +option swift_prefix = ""; + +// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. +// bytes fields of hashes are in canonical little-endian format. + +// Information about the state of the chain as of a given block. +message ChainMetadata { + uint32 saplingCommitmentTreeSize = 1; // the size of the Sapling note commitment tree as of the end of this block + uint32 orchardCommitmentTreeSize = 2; // the size of the Orchard note commitment tree as of the end of this block +} + +// A compact representation of the shielded data in a Zcash block. +// +// CompactBlock is a packaging of ONLY the data from a block that's needed to: +// 1. Detect a payment to your shielded Sapling address +// 2. Detect a spend of your shielded Sapling notes +// 3. Update your witnesses to generate new Sapling spend proofs. +message CompactBlock { + uint32 protoVersion = 1; // the version of this wire format, for storage + uint64 height = 2; // the height of this block + bytes hash = 3; // the ID (hash) of this block, same as in block explorers + bytes prevHash = 4; // the ID (hash) of this block's predecessor + uint32 time = 5; // Unix epoch time when the block was mined + bytes header = 6; // (hash, prevHash, and time) OR (full header) + repeated CompactTx vtx = 7; // zero or more compact transactions from this block + ChainMetadata chainMetadata = 8; // information about the state of the chain as of this block +} + +// A compact representation of the shielded data in a Zcash transaction. +// +// CompactTx contains the minimum information for a wallet to know if this transaction +// is relevant to it (either pays to it or spends from it) via shielded elements +// only. This message will not encode a transparent-to-transparent transaction. +message CompactTx { + // Index and hash will allow the receiver to call out to chain + // explorers or other data structures to retrieve more information + // about this transaction. + uint64 index = 1; // the index within the full block + bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers + + // The transaction fee: present if server can provide. In the case of a + // stateless server and a transaction with transparent inputs, this will be + // unset because the calculation requires reference to prior transactions. + // If there are no transparent inputs, the fee will be calculable as: + // valueBalanceSapling + valueBalanceOrchard + sum(vPubNew) - sum(vPubOld) - sum(tOut) + uint32 fee = 3; + + repeated CompactSaplingSpend spends = 4; + repeated CompactSaplingOutput outputs = 5; + repeated CompactOrchardAction actions = 6; +} + +// A compact representation of a [Sapling Spend](https://zips.z.cash/protocol/protocol.pdf#spendencodingandconsensus). +// +// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash +// protocol specification. +message CompactSaplingSpend { + bytes nf = 1; // Nullifier (see the Zcash protocol specification) +} + +// A compact representation of a [Sapling Output](https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus). +// +// It encodes the `cmu` field, `ephemeralKey` field, and a 52-byte prefix of the +// `encCiphertext` field of a Sapling Output Description. Total size is 116 bytes. +message CompactSaplingOutput { + bytes cmu = 1; // Note commitment u-coordinate. + bytes ephemeralKey = 2; // Ephemeral public key. + bytes ciphertext = 3; // First 52 bytes of ciphertext. +} + +// A compact representation of an [Orchard Action](https://zips.z.cash/protocol/protocol.pdf#actionencodingandconsensus). +message CompactOrchardAction { + bytes nullifier = 1; // [32] The nullifier of the input note + bytes cmx = 2; // [32] The x-coordinate of the note commitment for the output note + bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key + bytes ciphertext = 4; // [52] The first 52 bytes of the encCiphertext field +} diff --git a/zingo-rpc/proto/proposal.proto b/zingo-rpc/proto/proposal.proto new file mode 100644 index 0000000..db548c6 --- /dev/null +++ b/zingo-rpc/proto/proposal.proto @@ -0,0 +1,144 @@ +// Copyright (c) 2023 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +syntax = "proto3"; +package cash.z.wallet.sdk.ffi; + +// A data structure that describes a series of transactions to be created. +message Proposal { + // The version of this serialization format. + uint32 protoVersion = 1; + // The fee rule used in constructing this proposal + FeeRule feeRule = 2; + // The target height for which the proposal was constructed + // + // The chain must contain at least this many blocks in order for the proposal to + // be executed. + uint32 minTargetHeight = 3; + // The series of transactions to be created. + repeated ProposalStep steps = 4; +} + +// A data structure that describes the inputs to be consumed and outputs to +// be produced in a proposed transaction. +message ProposalStep { + // ZIP 321 serialized transaction request + string transactionRequest = 1; + // The vector of selected payment index / output pool mappings. Payment index + // 0 corresponds to the payment with no explicit index. + repeated PaymentOutputPool paymentOutputPools = 2; + // The anchor height to be used in creating the transaction, if any. + // Setting the anchor height to zero will disallow the use of any shielded + // inputs. + uint32 anchorHeight = 3; + // The inputs to be used in creating the transaction. + repeated ProposedInput inputs = 4; + // The total value, fee value, and change outputs of the proposed + // transaction + TransactionBalance balance = 5; + // A flag indicating whether the step is for a shielding transaction, + // used for determining which OVK to select for wallet-internal outputs. + bool isShielding = 6; +} + +enum ValuePool { + // Protobuf requires that enums have a zero discriminant as the default + // value. However, we need to require that a known value pool is selected, + // and we do not want to fall back to any default, so sending the + // PoolNotSpecified value will be treated as an error. + PoolNotSpecified = 0; + // The transparent value pool (P2SH is not distinguished from P2PKH) + Transparent = 1; + // The Sapling value pool + Sapling = 2; + // The Orchard value pool + Orchard = 3; +} + +// A mapping from ZIP 321 payment index to the output pool that has been chosen +// for that payment, based upon the payment address and the selected inputs to +// the transaction. +message PaymentOutputPool { + uint32 paymentIndex = 1; + ValuePool valuePool = 2; +} + +// The unique identifier and value for each proposed input that does not +// require a back-reference to a prior step of the proposal. +message ReceivedOutput { + bytes txid = 1; + ValuePool valuePool = 2; + uint32 index = 3; + uint64 value = 4; +} + +// A reference to a payment in a prior step of the proposal. This payment must +// belong to the wallet. +message PriorStepOutput { + uint32 stepIndex = 1; + uint32 paymentIndex = 2; +} + +// A reference to a change or ephemeral output from a prior step of the proposal. +message PriorStepChange { + uint32 stepIndex = 1; + uint32 changeIndex = 2; +} + +// The unique identifier and value for an input to be used in the transaction. +message ProposedInput { + oneof value { + ReceivedOutput receivedOutput = 1; + PriorStepOutput priorStepOutput = 2; + PriorStepChange priorStepChange = 3; + } +} + +// The fee rule used in constructing a Proposal +enum FeeRule { + // Protobuf requires that enums have a zero discriminant as the default + // value. However, we need to require that a known fee rule is selected, + // and we do not want to fall back to any default, so sending the + // FeeRuleNotSpecified value will be treated as an error. + FeeRuleNotSpecified = 0; + // 10000 ZAT + PreZip313 = 1; + // 1000 ZAT + Zip313 = 2; + // MAX(10000, 5000 * logical_actions) ZAT + Zip317 = 3; +} + +// The proposed change outputs and fee value. +message TransactionBalance { + // A list of change or ephemeral output values. + repeated ChangeValue proposedChange = 1; + // The fee to be paid by the proposed transaction, in zatoshis. + uint64 feeRequired = 2; +} + +// A proposed change or ephemeral output. If the transparent value pool is +// selected, the `memo` field must be null. +// +// When the `isEphemeral` field of a `ChangeValue` is set, it represents +// an ephemeral output, which must be spent by a subsequent step. This is +// only supported for transparent outputs. Each ephemeral output will be +// given a unique t-address. +message ChangeValue { + // The value of a change or ephemeral output to be created, in zatoshis. + uint64 value = 1; + // The value pool in which the change or ephemeral output should be created. + ValuePool valuePool = 2; + // The optional memo that should be associated with the newly created output. + // Memos must not be present for transparent outputs. + MemoBytes memo = 3; + // Whether this is to be an ephemeral output. + bool isEphemeral = 4; +} + +// An object wrapper for memo bytes, to facilitate representing the +// `change_memo == None` case. +message MemoBytes { + bytes value = 1; +} diff --git a/zingo-rpc/proto/service.proto b/zingo-rpc/proto/service.proto new file mode 100644 index 0000000..0945661 --- /dev/null +++ b/zingo-rpc/proto/service.proto @@ -0,0 +1,211 @@ +// Copyright (c) 2019-2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +syntax = "proto3"; +package cash.z.wallet.sdk.rpc; +option go_package = "lightwalletd/walletrpc"; +option swift_prefix = ""; +import "compact_formats.proto"; + +// A BlockID message contains identifiers to select a block: a height or a +// hash. Specification by hash is not implemented, but may be in the future. +message BlockID { + uint64 height = 1; + bytes hash = 2; +} + +// BlockRange specifies a series of blocks from start to end inclusive. +// Both BlockIDs must be heights; specification by hash is not yet supported. +message BlockRange { + BlockID start = 1; + BlockID end = 2; +} + +// A TxFilter contains the information needed to identify a particular +// transaction: either a block and an index, or a direct transaction hash. +// Currently, only specification by hash is supported. +message TxFilter { + BlockID block = 1; // block identifier, height or hash + uint64 index = 2; // index within the block + bytes hash = 3; // transaction ID (hash, txid) +} + +// RawTransaction contains the complete transaction data. It also optionally includes +// the block height in which the transaction was included, or, when returned +// by GetMempoolStream(), the latest block height. +message RawTransaction { + bytes data = 1; // exact data returned by Zcash 'getrawtransaction' + uint64 height = 2; // height that the transaction was mined (or -1) +} + +// A SendResponse encodes an error code and a string. It is currently used +// only by SendTransaction(). If error code is zero, the operation was +// successful; if non-zero, it and the message specify the failure. +message SendResponse { + int32 errorCode = 1; + string errorMessage = 2; +} + +// Chainspec is a placeholder to allow specification of a particular chain fork. +message ChainSpec {} + +// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. +message Empty {} + +// LightdInfo returns various information about this lightwalletd instance +// and the state of the blockchain. +message LightdInfo { + string version = 1; + string vendor = 2; + bool taddrSupport = 3; // true + string chainName = 4; // either "main" or "test" + uint64 saplingActivationHeight = 5; // depends on mainnet or testnet + string consensusBranchId = 6; // protocol identifier, see consensus/upgrades.cpp + uint64 blockHeight = 7; // latest block on the best chain + string gitCommit = 8; + string branch = 9; + string buildDate = 10; + string buildUser = 11; + uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing + string zcashdBuild = 13; // example: "v4.1.1-877212414" + string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/" +} + +// TransparentAddressBlockFilter restricts the results to the given address +// or block range. +message TransparentAddressBlockFilter { + string address = 1; // t-address + BlockRange range = 2; // start, end heights +} + +// Duration is currently used only for testing, so that the Ping rpc +// can simulate a delay, to create many simultaneous connections. Units +// are microseconds. +message Duration { + int64 intervalUs = 1; +} + +// PingResponse is used to indicate concurrency, how many Ping rpcs +// are executing upon entry and upon exit (after the delay). +// This rpc is used for testing only. +message PingResponse { + int64 entry = 1; + int64 exit = 2; +} + +message Address { + string address = 1; +} +message AddressList { + repeated string addresses = 1; +} +message Balance { + int64 valueZat = 1; +} + +message Exclude { + repeated bytes txid = 1; +} + +// The TreeState is derived from the Zcash z_gettreestate rpc. +message TreeState { + string network = 1; // "main" or "test" + uint64 height = 2; // block height + string hash = 3; // block id + uint32 time = 4; // Unix epoch time when the block was mined + string saplingTree = 5; // sapling commitment tree state + string orchardTree = 6; // orchard commitment tree state +} + +enum ShieldedProtocol { + sapling = 0; + orchard = 1; +} + +message GetSubtreeRootsArg { + uint32 startIndex = 1; // Index identifying where to start returning subtree roots + ShieldedProtocol shieldedProtocol = 2; // Shielded protocol to return subtree roots for + uint32 maxEntries = 3; // Maximum number of entries to return, or 0 for all entries. +} +message SubtreeRoot { + bytes rootHash = 2; // The 32-byte Merkle root of the subtree. + bytes completingBlockHash = 3; // The hash of the block that completed this subtree. + uint64 completingBlockHeight = 4; // The height of the block that completed this subtree in the main chain. +} + +// Results are sorted by height, which makes it easy to issue another +// request that picks up from where the previous left off. +message GetAddressUtxosArg { + repeated string addresses = 1; + uint64 startHeight = 2; + uint32 maxEntries = 3; // zero means unlimited +} +message GetAddressUtxosReply { + string address = 6; + bytes txid = 1; + int32 index = 2; + bytes script = 3; + int64 valueZat = 4; + uint64 height = 5; +} +message GetAddressUtxosReplyList { + repeated GetAddressUtxosReply addressUtxos = 1; +} + +service CompactTxStreamer { + // Return the height of the tip of the best chain + rpc GetLatestBlock(ChainSpec) returns (BlockID) {} + // Return the compact block corresponding to the given block identifier + rpc GetBlock(BlockID) returns (CompactBlock) {} + // Same as GetBlock except actions contain only nullifiers + rpc GetBlockNullifiers(BlockID) returns (CompactBlock) {} + // Return a list of consecutive compact blocks + rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} + // Same as GetBlockRange except actions contain only nullifiers + rpc GetBlockRangeNullifiers(BlockRange) returns (stream CompactBlock) {} + + // Return the requested full (not compact) transaction (as from zcashd) + rpc GetTransaction(TxFilter) returns (RawTransaction) {} + // Submit the given transaction to the Zcash network + rpc SendTransaction(RawTransaction) returns (SendResponse) {} + + // Return the txids corresponding to the given t-address within the given block range + rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {} + rpc GetTaddressBalance(AddressList) returns (Balance) {} + rpc GetTaddressBalanceStream(stream Address) returns (Balance) {} + + // Return the compact transactions currently in the mempool; the results + // can be a few seconds out of date. If the Exclude list is empty, return + // all transactions; otherwise return all *except* those in the Exclude list + // (if any); this allows the client to avoid receiving transactions that it + // already has (from an earlier call to this rpc). The transaction IDs in the + // Exclude list can be shortened to any number of bytes to make the request + // more bandwidth-efficient; if two or more transactions in the mempool + // match a shortened txid, they are all sent (none is excluded). Transactions + // in the exclude list that don't exist in the mempool are ignored. + rpc GetMempoolTx(Exclude) returns (stream CompactTx) {} + + // Return a stream of current Mempool transactions. This will keep the output stream open while + // there are mempool transactions. It will close the returned stream when a new block is mined. + rpc GetMempoolStream(Empty) returns (stream RawTransaction) {} + + // GetTreeState returns the note commitment tree state corresponding to the given block. + // See section 3.7 of the Zcash protocol specification. It returns several other useful + // values also (even though they can be obtained using GetBlock). + // The block can be specified by either height or hash. + rpc GetTreeState(BlockID) returns (TreeState) {} + rpc GetLatestTreeState(Empty) returns (TreeState) {} + + // Returns a stream of information about roots of subtrees of the Sapling and Orchard + // note commitment trees. + rpc GetSubtreeRoots(GetSubtreeRootsArg) returns (stream SubtreeRoot) {} + + rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} + rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {} + + // Return information about this lightwalletd instance and the blockchain + rpc GetLightdInfo(Empty) returns (LightdInfo) {} + // Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) + rpc Ping(Duration) returns (PingResponse) {} +} diff --git a/zingo-rpc/src/blockcache.rs b/zingo-rpc/src/blockcache.rs index a68f1da..cc42278 100644 --- a/zingo-rpc/src/blockcache.rs +++ b/zingo-rpc/src/blockcache.rs @@ -1,6 +1,7 @@ //! Zingo-Proxy Block Cache and Mempool State Engine. pub mod block; +pub mod error; pub mod mempool; pub mod transaction; pub mod utils; diff --git a/zingo-rpc/src/blockcache/block.rs b/zingo-rpc/src/blockcache/block.rs index 024b4b7..0265404 100644 --- a/zingo-rpc/src/blockcache/block.rs +++ b/zingo-rpc/src/blockcache/block.rs @@ -2,18 +2,18 @@ use crate::{ blockcache::{ + error::{BlockCacheError, ParseError}, transaction::FullTransaction, utils::{ display_txids_to_server, read_bytes, read_i32, read_u32, read_zcash_script_i64, - ParseError, ParseFromSlice, + CompactSize, ParseFromSlice, }, }, jsonrpc::{connector::JsonRpcConnector, primitives::GetBlockResponse}, + proto::compact_formats::{ChainMetadata, CompactBlock}, }; use sha2::{Digest, Sha256}; use std::io::Cursor; -use zcash_client_backend::proto::compact_formats::{ChainMetadata, CompactBlock}; -use zcash_encoding::CompactSize; /// A block header, containing metadata about a block. /// @@ -384,7 +384,7 @@ impl FullBlock { pub async fn get_block_from_node( zebra_uri: &http::Uri, height: &u32, -) -> Result { +) -> Result { let zebrad_client = JsonRpcConnector::new( zebra_uri.clone(), Some("xxxxxx".to_string()), @@ -410,9 +410,9 @@ pub async fn get_block_from_node( time: _, tx: _, trees: _, - }) => Err(ParseError::InvalidData( + }) => Err(BlockCacheError::ParseError(ParseError::InvalidData( "Received object block type, this should not be possible here.".to_string(), - )), + ))), Ok(GetBlockResponse::Raw(block_hex)) => Ok(FullBlock::parse_to_compact( block_hex.as_ref(), Some(display_txids_to_server(tx)?), @@ -422,9 +422,9 @@ pub async fn get_block_from_node( Err(e) => Err(e.into()), } } - Ok(GetBlockResponse::Raw(_)) => Err(ParseError::InvalidData( + Ok(GetBlockResponse::Raw(_)) => Err(BlockCacheError::ParseError(ParseError::InvalidData( "Received raw block type, this should not be possible here.".to_string(), - )), + ))), Err(e) => Err(e.into()), } } diff --git a/zingo-rpc/src/blockcache/error.rs b/zingo-rpc/src/blockcache/error.rs new file mode 100644 index 0000000..2f9d48d --- /dev/null +++ b/zingo-rpc/src/blockcache/error.rs @@ -0,0 +1,53 @@ +//! Hold error types for the BlockCache and related functionality. + +use crate::jsonrpc::error::JsonRpcConnectorError; + +/// Parser Error Type. +#[derive(Debug, thiserror::Error)] +pub enum ParseError { + /// Io Error. + #[error("IO Error: {0}")] + Io(#[from] std::io::Error), + + /// Invalid Data Error + #[error("Invalid Data Error: {0}")] + InvalidData(String), + + // /// Errors from the JsonRPC client. + // #[error("JsonRPC Connector Error: {0}")] + // JsonRpcError(#[from] JsonRpcConnectorError), + /// UTF-8 conversion error. + #[error("UTF-8 Error: {0}")] + Utf8Error(#[from] std::str::Utf8Error), + + /// UTF-8 conversion error. + #[error("UTF-8 Conversion Error: {0}")] + FromUtf8Error(#[from] std::string::FromUtf8Error), + + /// Hexadecimal parsing error. + #[error("Hex Parse Error: {0}")] + ParseIntError(#[from] std::num::ParseIntError), + + /// Errors originating from prost decodings. + #[error("Prost Decode Error: {0}")] + ProstDecodeError(#[from] prost::DecodeError), +} + +/// Parser Error Type. +#[derive(Debug, thiserror::Error)] +pub enum BlockCacheError { + /// Serialization and deserialization error. + #[error("Parser Error: {0}")] + ParseError(#[from] ParseError), + /// Errors from the JsonRPC client. + #[error("JsonRPC Connector Error: {0}")] + JsonRpcError(#[from] JsonRpcConnectorError), +} + +/// Mempool Error struct. +#[derive(thiserror::Error, Debug)] +pub enum MempoolError { + /// Errors from the JsonRPC client. + #[error("JsonRPC Connector Error: {0}")] + JsonRpcError(#[from] JsonRpcConnectorError), +} diff --git a/zingo-rpc/src/blockcache/mempool.rs b/zingo-rpc/src/blockcache/mempool.rs index 62f373d..62fa5c3 100644 --- a/zingo-rpc/src/blockcache/mempool.rs +++ b/zingo-rpc/src/blockcache/mempool.rs @@ -3,7 +3,10 @@ use std::{collections::HashSet, time::SystemTime}; use tokio::sync::{Mutex, RwLock}; -use crate::jsonrpc::connector::{JsonRpcConnector, JsonRpcConnectorError}; +use crate::{ + blockcache::error::MempoolError, jsonrpc::connector::JsonRpcConnector, + primitives::block::BlockHash, +}; /// Mempool state information. pub struct Mempool { @@ -14,15 +17,7 @@ pub struct Mempool { /// System time when the mempool was last updated. last_sync_time: Mutex, /// Blockchain data, used to check when a new block has been mined. - best_block_hash: RwLock>, -} - -/// Mempool Error struct. -#[derive(thiserror::Error, Debug)] -pub enum MempoolError { - /// Errors from the JsonRPC client. - #[error("JsonRPC Connector Error: {0}")] - JsonRpcError(#[from] JsonRpcConnectorError), + best_block_hash: RwLock>, } impl Default for Mempool { @@ -128,9 +123,7 @@ impl Mempool { } /// Returns the hash of the block currently in the mempool. - pub async fn get_best_block_hash( - &self, - ) -> Result, MempoolError> { + pub async fn get_best_block_hash(&self) -> Result, MempoolError> { let best_block_hash = self.best_block_hash.read().await; Ok(*best_block_hash) } diff --git a/zingo-rpc/src/blockcache/transaction.rs b/zingo-rpc/src/blockcache/transaction.rs index 22a98cd..cc762e5 100644 --- a/zingo-rpc/src/blockcache/transaction.rs +++ b/zingo-rpc/src/blockcache/transaction.rs @@ -1,13 +1,15 @@ //! Transaction fetching and deserialization functionality. -use crate::blockcache::utils::{ - read_bytes, read_u32, read_u64, skip_bytes, ParseError, ParseFromSlice, +use crate::{ + blockcache::{ + error::ParseError, + utils::{read_bytes, read_u32, read_u64, skip_bytes, CompactSize, ParseFromSlice}, + }, + proto::compact_formats::{ + CompactOrchardAction, CompactSaplingOutput, CompactSaplingSpend, CompactTx, + }, }; use std::io::Cursor; -use zcash_client_backend::proto::compact_formats::{ - CompactOrchardAction, CompactSaplingOutput, CompactSaplingSpend, CompactTx, -}; -use zcash_encoding::CompactSize; /// Txin format as described in https://en.bitcoin.it/wiki/Transaction #[derive(Debug)] diff --git a/zingo-rpc/src/blockcache/utils.rs b/zingo-rpc/src/blockcache/utils.rs index 04d1f2d..79a09da 100644 --- a/zingo-rpc/src/blockcache/utils.rs +++ b/zingo-rpc/src/blockcache/utils.rs @@ -1,37 +1,9 @@ //! Blockcache utility functionality. -use byteorder::{LittleEndian, ReadBytesExt}; -use std::io::{Cursor, Read}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::io::{self, Cursor, Read, Write}; -use crate::jsonrpc::connector::JsonRpcConnectorError; - -/// Parser Error Type. -/// -/// TODO: Move this error and other Zingo-Proxy error types intoown errors mod. -#[derive(Debug, thiserror::Error)] -pub enum ParseError { - /// Io Error. - #[error("IO Error: {0}")] - Io(#[from] std::io::Error), - /// Invalid Data Error - #[error("Invalid Data Error: {0}")] - InvalidData(String), - /// Errors from the JsonRPC client. - #[error("JsonRPC Connector Error: {0}")] - JsonRpcError(#[from] JsonRpcConnectorError), - /// UTF-8 conversion error. - #[error("UTF-8 Error: {0}")] - Utf8Error(#[from] std::str::Utf8Error), - /// UTF-8 conversion error. - #[error("UTF-8 Conversion Error: {0}")] - FromUtf8Error(#[from] std::string::FromUtf8Error), - /// Hexadecimal parsing error. - #[error("Hex Parse Error: {0}")] - ParseIntError(#[from] std::num::ParseIntError), - /// Errors originating from prost decodings. - #[error("Prost Decode Error: {0}")] - ProstDecodeError(#[from] prost::DecodeError), -} +use crate::blockcache::error::ParseError; /// Used for decoding zcash blocks from a bytestring. pub trait ParseFromSlice { @@ -134,6 +106,90 @@ pub fn read_zcash_script_i64(cursor: &mut Cursor<&[u8]>) -> Result(mut reader: R) -> io::Result { + let flag = reader.read_u8()?; + let result = if flag < 253 { + Ok(flag as u64) + } else if flag == 253 { + match reader.read_u16::()? { + n if n < 253 => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "non-canonical CompactSize", + )), + n => Ok(n as u64), + } + } else if flag == 254 { + match reader.read_u32::()? { + n if n < 0x10000 => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "non-canonical CompactSize", + )), + n => Ok(n as u64), + } + } else { + match reader.read_u64::()? { + n if n < 0x100000000 => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "non-canonical CompactSize", + )), + n => Ok(n), + } + }?; + + match result { + s if s > ::from(MAX_COMPACT_SIZE) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "CompactSize too large", + )), + s => Ok(s), + } + } + + /// Reads an integer encoded in contact form and performs checked conversion + /// to the target type. + pub fn read_t>(mut reader: R) -> io::Result { + let n = Self::read(&mut reader)?; + ::try_from(n).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "CompactSize value exceeds range of target type.", + ) + }) + } + + /// Writes the provided `usize` value to the provided Writer in compact form. + pub fn write(mut writer: W, size: usize) -> io::Result<()> { + match size { + s if s < 253 => writer.write_u8(s as u8), + s if s <= 0xFFFF => { + writer.write_u8(253)?; + writer.write_u16::(s as u16) + } + s if s <= 0xFFFFFFFF => { + writer.write_u8(254)?; + writer.write_u32::(s as u32) + } + s => { + writer.write_u8(255)?; + writer.write_u64::(s as u64) + } + } + } +} + /// Takes a vec of big endian hex encoded txids and returns them as a vec of little endian raw bytes. pub fn display_txids_to_server(txids: Vec) -> Result>, ParseError> { txids diff --git a/zingo-rpc/src/jsonrpc.rs b/zingo-rpc/src/jsonrpc.rs index 8758253..481e80a 100644 --- a/zingo-rpc/src/jsonrpc.rs +++ b/zingo-rpc/src/jsonrpc.rs @@ -1,4 +1,5 @@ //! JsonRPC client used to send requests to Zebrad. pub mod connector; +pub mod error; pub mod primitives; diff --git a/zingo-rpc/src/jsonrpc/connector.rs b/zingo-rpc/src/jsonrpc/connector.rs index 19a6fef..8a9ce22 100644 --- a/zingo-rpc/src/jsonrpc/connector.rs +++ b/zingo-rpc/src/jsonrpc/connector.rs @@ -9,10 +9,13 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use std::sync::atomic::{AtomicI32, Ordering}; -use super::primitives::{ - BestBlockHashResponse, GetBalanceResponse, GetBlockResponse, GetBlockchainInfoResponse, - GetInfoResponse, GetSubtreesResponse, GetTransactionResponse, GetTreestateResponse, - GetUtxosResponse, SendTransactionResponse, TxidsResponse, +use crate::jsonrpc::{ + error::JsonRpcConnectorError, + primitives::{ + BestBlockHashResponse, GetBalanceResponse, GetBlockResponse, GetBlockchainInfoResponse, + GetInfoResponse, GetSubtreesResponse, GetTransactionResponse, GetTreestateResponse, + GetUtxosResponse, SendTransactionResponse, TxidsResponse, + }, }; #[derive(Serialize, Deserialize, Debug)] @@ -38,65 +41,6 @@ struct RpcError { data: Option, } -/// General error type for handling JsonRpcConnector errors. -#[derive(Debug, thiserror::Error)] -pub enum JsonRpcConnectorError { - /// Uncatogorized Errors. - #[error("{0}")] - CustomError(String), - - /// Serialization/Deserialization Errors. - #[error("Serialization/Deserialization Error: {0}")] - SerdeJsonError(#[from] serde_json::Error), - - /// HTTP Request Errors. - #[error("HTTP Request Error: {0}")] - HyperError(#[from] hyper::Error), - - ///HTTP Errors. - #[error("HTTP Error: {0}")] - HttpError(#[from] http::Error), - - /// Invalid URI Errors. - #[error("Invalid URI: {0}")] - InvalidUriError(#[from] http::uri::InvalidUri), - - /// UTF-8 Conversion Errors. - #[error("UTF-8 Conversion Error")] - Utf8Error(#[from] std::string::FromUtf8Error), - - /// Request Timeout Errors. - #[error("Request Timeout Error")] - TimeoutError(#[from] tokio::time::error::Elapsed), -} - -impl JsonRpcConnectorError { - /// Constructor for errors without an underlying source - pub fn new(msg: impl Into) -> Self { - JsonRpcConnectorError::CustomError(msg.into()) - } - - /// Maps JsonRpcConnectorError to tonic::Status - pub fn to_grpc_status(&self) -> tonic::Status { - eprintln!("@zingoproxyd: Error occurred: {}.", self); - - match self { - JsonRpcConnectorError::SerdeJsonError(_) => { - tonic::Status::invalid_argument(self.to_string()) - } - JsonRpcConnectorError::HyperError(_) => tonic::Status::unavailable(self.to_string()), - JsonRpcConnectorError::HttpError(_) => tonic::Status::internal(self.to_string()), - _ => tonic::Status::internal(self.to_string()), - } - } -} - -impl From for tonic::Status { - fn from(err: JsonRpcConnectorError) -> Self { - err.to_grpc_status() - } -} - /// JsonRPC Client config data. pub struct JsonRpcConnector { uri: http::Uri, @@ -152,8 +96,8 @@ impl JsonRpcConnector { request_builder = request_builder.header("Authorization", format!("Basic {}", auth)); } - let request_body = serde_json::to_string(&req) - .map_err(JsonRpcConnectorError::SerdeJsonError)?; + let request_body = + serde_json::to_string(&req).map_err(JsonRpcConnectorError::SerdeJsonError)?; let request = request_builder .body(Body::from(request_body)) .map_err(JsonRpcConnectorError::HttpError)?; diff --git a/zingo-rpc/src/jsonrpc/error.rs b/zingo-rpc/src/jsonrpc/error.rs new file mode 100644 index 0000000..0dd3c74 --- /dev/null +++ b/zingo-rpc/src/jsonrpc/error.rs @@ -0,0 +1,60 @@ +//! Hold error types for the JsonRpcConnector and related functionality. + +/// General error type for handling JsonRpcConnector errors. +#[derive(Debug, thiserror::Error)] +pub enum JsonRpcConnectorError { + /// Uncatogorized Errors. + #[error("{0}")] + CustomError(String), + + /// Serialization/Deserialization Errors. + #[error("Serialization/Deserialization Error: {0}")] + SerdeJsonError(#[from] serde_json::Error), + + /// HTTP Request Errors. + #[error("HTTP Request Error: {0}")] + HyperError(#[from] hyper::Error), + + ///HTTP Errors. + #[error("HTTP Error: {0}")] + HttpError(#[from] http::Error), + + /// Invalid URI Errors. + #[error("Invalid URI: {0}")] + InvalidUriError(#[from] http::uri::InvalidUri), + + /// UTF-8 Conversion Errors. + #[error("UTF-8 Conversion Error")] + Utf8Error(#[from] std::string::FromUtf8Error), + + /// Request Timeout Errors. + #[error("Request Timeout Error")] + TimeoutError(#[from] tokio::time::error::Elapsed), +} + +impl JsonRpcConnectorError { + /// Constructor for errors without an underlying source + pub fn new(msg: impl Into) -> Self { + JsonRpcConnectorError::CustomError(msg.into()) + } + + /// Maps JsonRpcConnectorError to tonic::Status + pub fn to_grpc_status(&self) -> tonic::Status { + eprintln!("@zingoproxyd: Error occurred: {}.", self); + + match self { + JsonRpcConnectorError::SerdeJsonError(_) => { + tonic::Status::invalid_argument(self.to_string()) + } + JsonRpcConnectorError::HyperError(_) => tonic::Status::unavailable(self.to_string()), + JsonRpcConnectorError::HttpError(_) => tonic::Status::internal(self.to_string()), + _ => tonic::Status::internal(self.to_string()), + } + } +} + +impl From for tonic::Status { + fn from(err: JsonRpcConnectorError) -> Self { + err.to_grpc_status() + } +} diff --git a/zingo-rpc/src/jsonrpc/primitives.rs b/zingo-rpc/src/jsonrpc/primitives.rs index e26abe3..7d8772d 100644 --- a/zingo-rpc/src/jsonrpc/primitives.rs +++ b/zingo-rpc/src/jsonrpc/primitives.rs @@ -1,17 +1,18 @@ //! Request and response types for jsonRPC client. -use hex::{FromHex, ToHex}; use indexmap::IndexMap; -use serde::ser::SerializeStruct; -use serde::{Deserialize, Serialize}; - -use zebra_chain::{ - block::{self, Height, SerializedBlock}, - subtree::NoteCommitmentSubtreeIndex, - transaction::{self}, - transparent, +use serde::Deserialize; + +use crate::primitives::{ + address::TransparentAddress, + block::{BlockHash, SerializedBlock}, + chain::{ConsensusBranchIdHex, NetworkUpgradeInfo, TipConsensusBranch}, + height::ChainHeight, + transaction::{ + BlockCommitmentTreeSize, CommitmentTreestate, NoteCommitmentSubtreeIndex, OrchardTreestate, + SaplingTreestate, SerializedTransaction, SubtreeRpcData, TransactionHash, ZcashScript, + }, }; -use zebra_rpc::methods::GetBlockHash; /// Response to a `getinfo` RPC request. /// @@ -24,59 +25,6 @@ pub struct GetInfoResponse { pub subversion: String, } -/// A hex-encoded [`ConsensusBranchId`] string. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)] -pub struct ProxyConsensusBranchIdHex( - #[serde(with = "hex")] pub zebra_chain::parameters::ConsensusBranchId, -); - -/// The activation status of a [`NetworkUpgrade`]. -#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum ProxyNetworkUpgradeStatus { - /// The network upgrade is currently active. - /// - /// Includes all network upgrades that have previously activated, - /// even if they are not the most recent network upgrade. - #[serde(rename = "active")] - Active, - - /// The network upgrade does not have an activation height. - #[serde(rename = "disabled")] - Disabled, - - /// The network upgrade has an activation height, but we haven't reached it yet. - #[serde(rename = "pending")] - Pending, -} - -/// Information about [`NetworkUpgrade`] activation. -#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct ProxyNetworkUpgradeInfo { - /// Name of upgrade, string. - pub name: zebra_chain::parameters::NetworkUpgrade, - - /// Block height of activation, numeric. - #[serde(rename = "activationheight")] - pub activation_height: Height, - - /// Status of upgrade, string. - pub status: ProxyNetworkUpgradeStatus, -} - -/// The [`ConsensusBranchId`]s for the tip and the next block. -/// -/// These branch IDs are different when the next block is a network upgrade activation block. -#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct ProxyTipConsensusBranch { - /// Branch ID used to validate the current chain tip, big-endian, hex-encoded. - #[serde(rename = "chaintip")] - pub chain_tip: ProxyConsensusBranchIdHex, - - /// Branch ID used to validate the next block, big-endian, hex-encoded. - #[serde(rename = "nextblock")] - pub next_block: ProxyConsensusBranchIdHex, -} - /// Response to a `getblockchaininfo` RPC request. /// /// This is used for the output parameter of [`JsonRpcConnector::get_blockchain_info`]. @@ -86,23 +34,23 @@ pub struct GetBlockchainInfoResponse { pub chain: String, /// The current number of blocks processed in the server, numeric - pub blocks: Height, + pub blocks: ChainHeight, /// The hash of the currently best block, in big-endian order, hex-encoded #[serde(rename = "bestblockhash", with = "hex")] - pub best_block_hash: block::Hash, + pub best_block_hash: BlockHash, /// If syncing, the estimated height of the chain, else the current best height, numeric. /// /// In Zebra, this is always the height estimate, so it might be a little inaccurate. #[serde(rename = "estimatedheight")] - pub estimated_height: Height, + pub estimated_height: ChainHeight, /// Status of network upgrades - pub upgrades: IndexMap, + pub upgrades: IndexMap, /// Branch IDs of the current and upcoming consensus rules - pub consensus: ProxyTipConsensusBranch, + pub consensus: TipConsensusBranch, } /// The transparent balance of a set of addresses. @@ -118,78 +66,21 @@ pub struct GetBalanceResponse { /// /// This is used for the output parameter of [`JsonRpcConnector::send_raw_transaction`]. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct SendTransactionResponse(#[serde(with = "hex")] pub transaction::Hash); - -/// Wrapper for `SerializedBlock` to handle hex serialization/deserialization. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ProxySerializedBlock(SerializedBlock); - -impl Serialize for ProxySerializedBlock { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let hex_string = self.as_ref().encode_hex::(); - serializer.serialize_str(&hex_string) - } -} - -impl<'de> Deserialize<'de> for ProxySerializedBlock { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct HexVisitor; - - impl<'de> serde::de::Visitor<'de> for HexVisitor { - type Value = ProxySerializedBlock; - - fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - formatter.write_str("a hex-encoded string") - } - - fn visit_str(self, value: &str) -> Result - where - E: serde::de::Error, - { - let bytes = hex::decode(value).map_err(serde::de::Error::custom)?; - Ok(ProxySerializedBlock(SerializedBlock::from(bytes))) - } - } +pub struct SendTransactionResponse(#[serde(with = "hex")] pub TransactionHash); - deserializer.deserialize_str(HexVisitor) - } -} - -impl FromHex for ProxySerializedBlock { - type Error = hex::FromHexError; - - fn from_hex>(hex: T) -> Result { - hex::decode(hex) - .map(|bytes| ProxySerializedBlock(SerializedBlock::from(bytes))) - } -} - -impl AsRef<[u8]> for ProxySerializedBlock { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -/// Sapling note commitment tree information. +/// Response to a `getbestblockhash` and `getblockhash` RPC request. +/// +/// Contains the hex-encoded hash of the requested block. +/// +/// Also see the notes for the [`Rpc::get_best_block_hash`] and `get_block_hash` methods. #[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxyTree { - /// Commitment tree size. - pub size: u64, -} +#[serde(transparent)] +pub struct GetBlockHash(#[serde(with = "hex")] pub BlockHash); -/// Information about the note commitment trees. -#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxyBlockTrees { - /// Sapling commitment tree size. - pub sapling: ProxyTree, - /// Orchard commitment tree size. - pub orchard: ProxyTree, +impl Default for GetBlockHash { + fn default() -> Self { + GetBlockHash(BlockHash([0; 32])) + } } /// Contains the hex-encoded hash of the sent transaction. @@ -199,7 +90,7 @@ pub struct ProxyBlockTrees { #[serde(untagged)] pub enum GetBlockResponse { /// The request block, hex-encoded. - Raw(#[serde(with = "hex")] ProxySerializedBlock), + Raw(#[serde(with = "hex")] SerializedBlock), /// The block object. Object { /// The hash of the requested block. @@ -211,7 +102,7 @@ pub enum GetBlockResponse { /// The height of the requested block. #[serde(skip_serializing_if = "Option::is_none")] - height: Option, + height: Option, /// The height of the requested block. #[serde(skip_serializing_if = "Option::is_none")] @@ -221,7 +112,7 @@ pub enum GetBlockResponse { tx: Vec, /// Information about the note commitment trees. - trees: ProxyBlockTrees, //zebra_rpc::methods::GetBlockTrees, + trees: BlockCommitmentTreeSize, }, } @@ -230,7 +121,7 @@ pub enum GetBlockResponse { /// This is used for the output parameter of [`JsonRpcConnector::get_best_block_hash`]. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(transparent)] -pub struct BestBlockHashResponse(#[serde(with = "hex")] pub block::Hash); +pub struct BestBlockHashResponse(#[serde(with = "hex")] pub BlockHash); /// Vec of transaction ids, as a JSON array. /// @@ -259,33 +150,6 @@ impl<'de> Deserialize<'de> for TxidsResponse { } } -/// Zingo-Proxy commitment tree structure replicating functionality in Zebra. -/// -/// A wrapper that contains either an Orchard or Sapling note commitment tree. -#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxyCommitments { - /// Commitment tree state - pub final_state: String, -} - -/// Zingo-Proxy sapling treestate. -/// -/// A treestate that is included in the [`z_gettreestate`][1] RPC response. -#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxySaplingTreestate { - /// Sapling note commitment tree. - pub commitments: ProxyCommitments, -} - -/// Zingo-Proxy orchard treestate. -/// -/// A treestate that is included in the [`z_gettreestate`][1] RPC response. -#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxyOrchardTreestate { - /// Sapling note commitment tree. - pub commitments: ProxyCommitments, -} - /// Contains the hex-encoded Sapling & Orchard note commitment trees, and their /// corresponding [`block::Hash`], [`Height`], and block time. /// @@ -304,10 +168,10 @@ pub struct GetTreestateResponse { pub time: u32, /// A treestate containing a Sapling note commitment tree, hex-encoded. - pub sapling: ProxySaplingTreestate, + pub sapling: SaplingTreestate, /// A treestate containing an Orchard note commitment tree, hex-encoded. - pub orchard: ProxyOrchardTreestate, + pub orchard: OrchardTreestate, } impl<'de> Deserialize<'de> for GetTreestateResponse { @@ -338,13 +202,13 @@ impl<'de> Deserialize<'de> for GetTreestateResponse { height, hash, time, - sapling: ProxySaplingTreestate { - commitments: ProxyCommitments { + sapling: SaplingTreestate { + commitments: CommitmentTreestate { final_state: sapling_final_state, }, }, - orchard: ProxyOrchardTreestate { - commitments: ProxyCommitments { + orchard: OrchardTreestate { + commitments: CommitmentTreestate { final_state: orchard_final_state, }, }, @@ -352,82 +216,18 @@ impl<'de> Deserialize<'de> for GetTreestateResponse { } } -/// A serialized transaction. -/// -/// Stores bytes that are guaranteed to be deserializable into a [`Transaction`]. -/// -/// Sorts in lexicographic order of the transaction's serialized data. -#[derive(Clone, Eq, PartialEq, serde::Serialize)] -pub struct ProxySerializedTransaction { - /// Transaction bytes. - pub bytes: Vec, -} - -impl std::fmt::Display for ProxySerializedTransaction { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str(&hex::encode(&self.bytes)) - } -} - -impl std::fmt::Debug for ProxySerializedTransaction { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let data_hex = hex::encode(&self.bytes); - - f.debug_tuple("ProxySerializedTransaction") - .field(&data_hex) - .finish() - } -} - -impl AsRef<[u8]> for ProxySerializedTransaction { - fn as_ref(&self) -> &[u8] { - self.bytes.as_ref() - } -} - -impl From> for ProxySerializedTransaction { - fn from(bytes: Vec) -> Self { - Self { bytes } - } -} - -impl FromHex for ProxySerializedTransaction { - type Error = as FromHex>::Error; - - fn from_hex>(hex: T) -> Result { - let bytes = >::from_hex(hex)?; - - Ok(bytes.into()) - } -} - -impl<'de> Deserialize<'de> for ProxySerializedTransaction { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let v = serde_json::Value::deserialize(deserializer)?; - if let Some(hex_str) = v.as_str() { - let bytes = hex::decode(hex_str).map_err(serde::de::Error::custom)?; - Ok(ProxySerializedTransaction { bytes }) - } else { - Err(serde::de::Error::custom("expected a hex string")) - } - } -} - /// Contains raw transaction, encoded as hex bytes. /// /// This is used for the output parameter of [`JsonRpcConnector::get_raw_transaction`]. #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] pub enum GetTransactionResponse { /// The raw transaction, encoded as hex bytes. - Raw(#[serde(with = "hex")] ProxySerializedTransaction), + Raw(#[serde(with = "hex")] SerializedTransaction), /// The transaction object. Object { /// The raw transaction, encoded as hex bytes. #[serde(with = "hex")] - hex: ProxySerializedTransaction, + hex: SerializedTransaction, /// The height of the block in the best chain that contains the transaction, or -1 if /// the transaction is in the mempool. height: i32, @@ -477,83 +277,14 @@ impl<'de> Deserialize<'de> for GetTransactionResponse { } /// *** THE FOLLOWING CODE IS CURRENTLY UNUSED BY ZINGO-PROXY AND UNTESTED! *** - -/// Wrapper type that can hold Sapling or Orchard subtree roots with hex encoding. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ProxySubtreeRpcData { - /// Merkle root of the 2^16-leaf subtree. - pub root: String, - /// Height of the block containing the note that completed this subtree. - pub height: Height, -} - -impl ProxySubtreeRpcData { - /// Returns new instance of ProxySubtreeRpcData - pub fn new(root: String, height: Height) -> Self { - Self { root, height } - } -} - -impl serde::Serialize for ProxySubtreeRpcData { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_struct("ProxySubtreeRpcData", 2)?; - state.serialize_field("root", &self.root)?; - state.serialize_field("height", &self.height)?; - state.end() - } -} - -impl<'de> serde::Deserialize<'de> for ProxySubtreeRpcData { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - #[derive(Deserialize)] - struct Inner { - root: String, - height: Height, - } - - let inner = Inner::deserialize(deserializer)?; - Ok(ProxySubtreeRpcData { - root: inner.root, - height: inner.height, - }) - } -} - -impl FromHex for ProxySubtreeRpcData { - type Error = hex::FromHexError; - - fn from_hex>(hex: T) -> Result { - let hex_str = std::str::from_utf8(hex.as_ref()) - .map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?; - - if hex_str.len() < 8 { - return Err(hex::FromHexError::OddLength); - } - - let root_end_index = hex_str.len() - 8; - let (root_hex, height_hex) = hex_str.split_at(root_end_index); - - let root = root_hex.to_string(); - let height = u32::from_str_radix(height_hex, 16) - .map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?; - - Ok(ProxySubtreeRpcData { - root, - height: Height(height), - }) - } -} +/// *** TEST BEFORE USE *** /// Contains the Sapling or Orchard pool label, the index of the first subtree in the list, /// and a list of subtree roots and end heights. /// /// This is used for the output parameter of [`JsonRpcConnector::get_subtrees_by_index`]. +/// +/// *** UNTESTED - TEST BEFORE USE *** #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetSubtreesResponse { /// The shielded pool to which the subtrees belong. @@ -566,107 +297,32 @@ pub struct GetSubtreesResponse { /// /// The generic subtree root type is a hex-encoded Sapling or Orchard subtree root string. // #[serde(skip_serializing_if = "Vec::is_empty")] - pub subtrees: Vec, -} - -/// Zingo-Proxy encoding of a Bitcoin script. -#[derive(Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct ProxyScript { - /// # Correctness - /// - /// Consensus-critical serialization uses [`ZcashSerialize`]. - /// [`serde`]-based hex serialization must only be used for RPCs and testing. - #[serde(with = "hex")] - pub script: Vec, + pub subtrees: Vec, } -impl ProxyScript { - /// Create a new Bitcoin script from its raw bytes. - /// The raw bytes must not contain the length prefix. - pub fn new(raw_bytes: &[u8]) -> Self { - Self { - script: raw_bytes.to_vec(), - } - } - - /// Return the raw bytes of the script without the length prefix. - /// - /// # Correctness - /// - /// These raw bytes do not have a length prefix. - /// The Zcash serialization format requires a length prefix; use `zcash_serialize` - /// and `zcash_deserialize` to create byte data with a length prefix. - pub fn as_raw_bytes(&self) -> &[u8] { - &self.script - } -} - -impl core::fmt::Display for ProxyScript { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.write_str(&self.encode_hex::()) - } -} - -impl core::fmt::Debug for ProxyScript { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_tuple("Script") - .field(&hex::encode(&self.script)) - .finish() - } -} - -impl ToHex for &ProxyScript { - fn encode_hex>(&self) -> T { - self.as_raw_bytes().encode_hex() - } - - fn encode_hex_upper>(&self) -> T { - self.as_raw_bytes().encode_hex_upper() - } -} - -impl ToHex for ProxyScript { - fn encode_hex>(&self) -> T { - (&self).encode_hex() - } - - fn encode_hex_upper>(&self) -> T { - (&self).encode_hex_upper() - } -} - -impl FromHex for ProxyScript { - type Error = hex::FromHexError; - - fn from_hex>(hex: T) -> Result { - let bytes = Vec::from_hex(hex)?; - Ok(Self { script: bytes }) - } -} - -/// . -/// /// This is used for the output parameter of [`JsonRpcConnector::get_address_utxos`]. +/// +/// *** UNTESTED - TEST BEFORE USE *** #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetUtxosResponse { /// The transparent address, base58check encoded - pub address: transparent::Address, + pub address: TransparentAddress, /// The output txid, in big-endian order, hex-encoded #[serde(with = "hex")] - pub txid: transaction::Hash, + pub txid: TransactionHash, /// The transparent output index, numeric #[serde(rename = "outputIndex")] - pub output_index: zebra_state::OutputIndex, + pub output_index: u32, /// The transparent output script, hex encoded #[serde(with = "hex")] - pub script: ProxyScript, + pub script: ZcashScript, /// The amount of zatoshis in the transparent output pub satoshis: u64, /// The block height, numeric. - pub height: Height, + pub height: ChainHeight, } diff --git a/zingo-rpc/src/lib.rs b/zingo-rpc/src/lib.rs index ba73e50..1345e0f 100644 --- a/zingo-rpc/src/lib.rs +++ b/zingo-rpc/src/lib.rs @@ -7,6 +7,7 @@ pub mod blockcache; pub mod jsonrpc; pub mod nym; pub mod primitives; +pub mod proto; pub mod queue; pub mod rpc; pub mod utils; diff --git a/zingo-rpc/src/nym.rs b/zingo-rpc/src/nym.rs index 8bfcd24..56012f7 100644 --- a/zingo-rpc/src/nym.rs +++ b/zingo-rpc/src/nym.rs @@ -1,4 +1,5 @@ //! Backend Nym functionality. pub mod client; +pub mod error; pub mod utils; diff --git a/zingo-rpc/src/nym/client.rs b/zingo-rpc/src/nym/client.rs index c7d613a..6a8e458 100644 --- a/zingo-rpc/src/nym/client.rs +++ b/zingo-rpc/src/nym/client.rs @@ -7,27 +7,24 @@ use nym_sdk::mixnet::{ }; use std::path::PathBuf; -use crate::primitives::NymClient; +use crate::{nym::error::NymError, primitives::client::NymClient}; impl NymClient { /// Spawns a nym client and connects to the mixnet. - pub async fn nym_spawn(str_path: &str) -> Self { + pub async fn nym_spawn(str_path: &str) -> Result { //nym_bin_common::logging::setup_logging(); - let client = MixnetClientBuilder::new_with_default_storage( - StoragePaths::new_from_dir(PathBuf::from(str_path)).unwrap(), - ) - .await - .unwrap() - .build() - .unwrap() + let client = MixnetClientBuilder::new_with_default_storage(StoragePaths::new_from_dir( + PathBuf::from(str_path), + )?) + .await? + .build()? .connect_to_mixnet() - .await - .unwrap(); + .await?; let nym_addr = client.nym_address().to_string(); println!("@zingoproxyd[nym]: Nym server listening on: {nym_addr}."); - Self(client) + Ok(Self(client)) } /// Forwards an encoded gRPC request over the nym mixnet to the nym address specified and waits for the response. @@ -37,10 +34,11 @@ impl NymClient { &mut self, recipient_address: &str, message: Vec, - ) -> Result, Box> { + ) -> Result, NymError> { + // Box> { let recipient: Recipient = - Recipient::try_from_base58_string(recipient_address.to_string()).unwrap(); - self.0.send_plain_message(recipient, message).await.unwrap(); + Recipient::try_from_base58_string(recipient_address.to_string())?; + self.0.send_plain_message(recipient, message).await?; let mut nym_response: Vec = Vec::new(); while let Some(response_in) = self.0.wait_for_messages().await { @@ -53,7 +51,9 @@ impl NymClient { let response_out = nym_response .first() .map(|r| r.message.clone()) - .ok_or_else(|| "No response received from the nym network".to_string())?; + .ok_or_else(|| { + NymError::ConnectionError("No response received from the nym network".to_string()) + })?; Ok(response_out) } diff --git a/zingo-rpc/src/nym/error.rs b/zingo-rpc/src/nym/error.rs new file mode 100644 index 0000000..a609530 --- /dev/null +++ b/zingo-rpc/src/nym/error.rs @@ -0,0 +1,37 @@ +//! Hold error types for Nym related functionality. + +use crate::blockcache::error::ParseError; + +/// Parser Error Type. +#[derive(Debug, thiserror::Error)] +pub enum NymError { + /// Serialization and deserialization error. + #[error("Parser Error: {0}")] + ParseError(#[from] ParseError), + /// Nym-SDK related error, look at specific types for detail. + /// + /// TODO: Handle certain Nym-SDK Errors specifically (network related errors, nym client startup..). + #[error("Nym-SDK Error: {0}")] + NymError(#[from] nym_sdk::Error), + /// Nym address formatting errors. + #[error("Nym Recipient Formatting Error Error: {0}")] + RecipientFormattingError(#[from] nym_sphinx_addressing::clients::RecipientFormattingError), + /// Mixnet connection error. + #[error("Connection Error: {0}")] + ConnectionError(String), +} + +impl From for tonic::Status { + fn from(error: NymError) -> Self { + match error { + NymError::ParseError(e) => tonic::Status::internal(format!("Parse error: {}", e)), + NymError::NymError(e) => tonic::Status::internal(format!("Nym-SDK error: {}", e)), + NymError::RecipientFormattingError(e) => { + tonic::Status::invalid_argument(format!("Recipient formatting error: {}", e)) + } + NymError::ConnectionError(e) => { + tonic::Status::internal(format!("Connection error: {}", e)) + } + } + } +} diff --git a/zingo-rpc/src/nym/utils.rs b/zingo-rpc/src/nym/utils.rs index 61e88b8..da4607a 100644 --- a/zingo-rpc/src/nym/utils.rs +++ b/zingo-rpc/src/nym/utils.rs @@ -1,26 +1,31 @@ //! Utility functions for Nym-Proxy +use crate::{ + blockcache::{ + error::ParseError, + utils::{read_bytes, CompactSize}, + }, + nym::error::NymError, +}; use std::io::Cursor; -use zcash_encoding::CompactSize; - -use crate::blockcache::utils::{read_bytes, ParseError}; /// Reads a RPC method name from a Vec and returns this as a string along with the remaining data in the input. -fn read_nym_method(data: &[u8]) -> Result<(String, &[u8]), ParseError> { +fn read_nym_method(data: &[u8]) -> Result<(String, &[u8]), NymError> { let mut cursor = Cursor::new(data); - let method_len = CompactSize::read(&mut cursor)? as usize; - let method = String::from_utf8(read_bytes(&mut cursor, method_len, "failed to read")?)?; + let method_len = CompactSize::read(&mut cursor).map_err(ParseError::Io)? as usize; + let method = String::from_utf8(read_bytes(&mut cursor, method_len, "failed to read")?) + .map_err(ParseError::FromUtf8Error)?; Ok((method, &data[cursor.position() as usize..])) } /// Check the body of the request is the correct length. -fn check_nym_body(data: &[u8]) -> Result<&[u8], ParseError> { +fn check_nym_body(data: &[u8]) -> Result<&[u8], NymError> { let mut cursor = Cursor::new(data); - let body_len = CompactSize::read(&mut cursor)? as usize; + let body_len = CompactSize::read(&mut cursor).map_err(ParseError::Io)? as usize; if &body_len != &data[cursor.position() as usize..].len() { - return Err(ParseError::InvalidData( + return Err(NymError::ParseError(ParseError::InvalidData( "Incorrect request body size read.".to_string(), - )); + ))); }; Ok(&data[cursor.position() as usize..]) } @@ -28,9 +33,9 @@ fn check_nym_body(data: &[u8]) -> Result<&[u8], ParseError> { /// Extracts metadata from a NymRequest. /// /// Returns [ID, Method, RequestData]. -pub fn read_nym_request_data(data: &[u8]) -> Result<(u64, String, &[u8]), ParseError> { +pub fn read_nym_request_data(data: &[u8]) -> Result<(u64, String, &[u8]), NymError> { let mut cursor = Cursor::new(data); - let id = CompactSize::read(&mut cursor)?; + let id = CompactSize::read(&mut cursor).map_err(ParseError::Io)?; let (method, data) = read_nym_method(&data[cursor.position() as usize..])?; let body = check_nym_body(data)?; Ok((id, method, body)) diff --git a/zingo-rpc/src/primitives.rs b/zingo-rpc/src/primitives.rs index 370cd4f..9aabb09 100644 --- a/zingo-rpc/src/primitives.rs +++ b/zingo-rpc/src/primitives.rs @@ -1,18 +1,11 @@ -//! Zingo-RPC primitives. +//! ZingoProxy and Zcash primitives. +//! +//! This is not an exaustive source of zcash primitives, only what Zingo-Proxy and consuming wallets [ZngoLib] require for their functionality. -use nym_sdk::mixnet::MixnetClient; -use std::sync::{atomic::AtomicBool, Arc}; - -/// Configuration data for gRPC server. -pub struct ProxyClient { - /// Lightwalletd uri. - /// Used by grpc_passthrough to pass on unimplemented RPCs. - pub lightwalletd_uri: http::Uri, - /// Zebrad uri. - pub zebrad_uri: http::Uri, - /// Represents the Online status of the gRPC server. - pub online: Arc, -} - -/// Wrapper struct for a Nym client. -pub struct NymClient(pub MixnetClient); +pub mod address; +pub mod block; +pub mod chain; +pub mod client; +pub mod error; +pub mod height; +pub mod transaction; diff --git a/zingo-rpc/src/primitives/address.rs b/zingo-rpc/src/primitives/address.rs new file mode 100644 index 0000000..9d05527 --- /dev/null +++ b/zingo-rpc/src/primitives/address.rs @@ -0,0 +1,63 @@ +//! Hold primitives relating to zcash addresses. + +use crate::primitives::chain::NetworkKind; +use std::fmt; + +/// *** THE FOLLOWING CODE IS CURRENTLY UNUSED BY ZINGO-PROXY AND UNTESTED! *** +/// *** TEST BEFORE USE *** + +/// Transparent Zcash Addresses +/// +/// In Bitcoin a single byte is used for the version field identifying +/// the address type. In Zcash two bytes are used. For addresses on +/// the production network, this and the encoded length cause the first +/// two characters of the Base58Check encoding to be fixed as "t3" for +/// P2SH addresses, and as "t1" for P2PKH addresses. (This does not +/// imply that a transparent Zcash address can be parsed identically +/// to a Bitcoin address just by removing the "t".) +/// +/// +/// +/// *** UNTESTED - TEST BEFORE USE *** +#[derive(Clone, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)] +pub enum TransparentAddress { + /// P2SH (Pay to Script Hash) addresses + PayToScriptHash { + /// Production, test, or other network + network_kind: NetworkKind, + /// 20 bytes specifying a script hash. + script_hash: [u8; 20], + }, + + /// P2PKH (Pay to Public Key Hash) addresses + PayToPublicKeyHash { + /// Production, test, or other network + network_kind: NetworkKind, + /// 20 bytes specifying a public key hash, which is a RIPEMD-160 + /// hash of a SHA-256 hash of a compressed ECDSA key encoding. + pub_key_hash: [u8; 20], + }, +} + +impl fmt::Debug for TransparentAddress { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut debug_struct = f.debug_struct("TransparentAddress"); + + match self { + TransparentAddress::PayToScriptHash { + network_kind, + script_hash, + } => debug_struct + .field("network_kind", network_kind) + .field("script_hash", &hex::encode(script_hash)) + .finish(), + TransparentAddress::PayToPublicKeyHash { + network_kind, + pub_key_hash, + } => debug_struct + .field("network_kind", network_kind) + .field("pub_key_hash", &hex::encode(pub_key_hash)) + .finish(), + } + } +} diff --git a/zingo-rpc/src/primitives/block.rs b/zingo-rpc/src/primitives/block.rs new file mode 100644 index 0000000..598ebed --- /dev/null +++ b/zingo-rpc/src/primitives/block.rs @@ -0,0 +1,165 @@ +//! Hold primitives relating to zcash blocks. + +use std::fmt; + +use crate::primitives::error::SerializationError; +use hex::{FromHex, ToHex}; + +/// A serialized block. +/// +/// Stores bytes that are guaranteed to be deserializable into a [`Block`]. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct SerializedBlock { + bytes: Vec, +} + +/// Access the serialized bytes of a [`SerializedBlock`]. +impl AsRef<[u8]> for SerializedBlock { + fn as_ref(&self) -> &[u8] { + self.bytes.as_ref() + } +} + +impl From> for SerializedBlock { + fn from(bytes: Vec) -> Self { + Self { bytes } + } +} + +impl serde::Serialize for SerializedBlock { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let hex_string = self.as_ref().encode_hex::(); + serializer.serialize_str(&hex_string) + } +} + +impl<'de> serde::Deserialize<'de> for SerializedBlock { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct HexVisitor; + + impl<'de> serde::de::Visitor<'de> for HexVisitor { + type Value = SerializedBlock; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a hex-encoded string") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + let bytes = hex::decode(value).map_err(serde::de::Error::custom)?; + Ok(SerializedBlock::from(bytes)) + } + } + + deserializer.deserialize_str(HexVisitor) + } +} + +impl FromHex for SerializedBlock { + type Error = hex::FromHexError; + + fn from_hex>(hex: T) -> Result { + hex::decode(hex).map(|bytes| SerializedBlock::from(bytes)) + } +} + +/// A hash of a block, used to identify blocks and link blocks into a chain. ⛓️ +/// +/// Technically, this is the (SHA256d) hash of a block *header*, but since the +/// block header includes the Merkle root of the transaction Merkle tree, it +/// binds the entire contents of the block and is used to identify entire blocks. +/// +/// Note: Zebra displays transaction and block hashes in big-endian byte-order, +/// following the u256 convention set by Bitcoin and zcashd. +/// +/// Taken from zebra-chain for consistancy. +#[derive(Copy, Clone, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)] +pub struct BlockHash(pub [u8; 32]); + +impl BlockHash { + /// Return the hash bytes in big-endian byte-order suitable for printing out byte by byte. + /// + /// Zebra displays transaction and block hashes in big-endian byte-order, + /// following the u256 convention set by Bitcoin and zcashd. + pub fn bytes_in_display_order(&self) -> [u8; 32] { + let mut reversed_bytes = self.0; + reversed_bytes.reverse(); + reversed_bytes + } + + /// Convert bytes in big-endian byte-order into a [`block::Hash`](crate::block::Hash). + /// + /// Zebra displays transaction and block hashes in big-endian byte-order, + /// following the u256 convention set by Bitcoin and zcashd. + pub fn from_bytes_in_display_order(bytes_in_display_order: &[u8; 32]) -> BlockHash { + let mut internal_byte_order = *bytes_in_display_order; + internal_byte_order.reverse(); + + BlockHash(internal_byte_order) + } +} + +impl fmt::Display for BlockHash { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.encode_hex::()) + } +} + +impl fmt::Debug for BlockHash { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("block::Hash") + .field(&self.encode_hex::()) + .finish() + } +} + +impl ToHex for &BlockHash { + fn encode_hex>(&self) -> T { + self.bytes_in_display_order().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.bytes_in_display_order().encode_hex_upper() + } +} + +impl ToHex for BlockHash { + fn encode_hex>(&self) -> T { + (&self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + (&self).encode_hex_upper() + } +} + +impl FromHex for BlockHash { + type Error = <[u8; 32] as FromHex>::Error; + + fn from_hex>(hex: T) -> Result { + let hash = <[u8; 32]>::from_hex(hex)?; + + Ok(Self::from_bytes_in_display_order(&hash)) + } +} + +impl From<[u8; 32]> for BlockHash { + fn from(bytes: [u8; 32]) -> Self { + Self(bytes) + } +} + +impl std::str::FromStr for BlockHash { + type Err = SerializationError; + fn from_str(s: &str) -> Result { + Ok(Self::from_hex(s)?) + } +} diff --git a/zingo-rpc/src/primitives/chain.rs b/zingo-rpc/src/primitives/chain.rs new file mode 100644 index 0000000..b140242 --- /dev/null +++ b/zingo-rpc/src/primitives/chain.rs @@ -0,0 +1,176 @@ +//! Hold primitives relating to chain and network. + +use std::fmt; + +use hex::ToHex; + +use crate::primitives::height::ChainHeight; + +/// An enum describing the kind of network, whether it's the production mainnet or a testnet. +// Note: The order of these variants is important for correct bincode (de)serialization +// of history trees in the db format. +#[derive( + Copy, Clone, Default, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, +)] +pub enum NetworkKind { + /// The production mainnet. + #[default] + Mainnet, + + /// A test network. + Testnet, + + /// Regtest mode. + Regtest, +} + +/// The Consensus Branch Id, used to bind transactions and blocks to a +/// particular network upgrade. +#[derive( + Copy, Clone, Debug, Default, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize, +)] +pub struct ConsensusBranchId(u32); + +impl ConsensusBranchId { + /// Return the hash bytes in big-endian byte-order suitable for printing out byte by byte. + /// + /// Zebra displays consensus branch IDs in big-endian byte-order, + /// following the convention set by zcashd. + fn bytes_in_display_order(&self) -> [u8; 4] { + self.0.to_be_bytes() + } +} + +impl From for u32 { + fn from(branch: ConsensusBranchId) -> u32 { + branch.0 + } +} + +impl hex::ToHex for &ConsensusBranchId { + fn encode_hex>(&self) -> T { + self.bytes_in_display_order().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.bytes_in_display_order().encode_hex_upper() + } +} + +impl hex::ToHex for ConsensusBranchId { + fn encode_hex>(&self) -> T { + self.bytes_in_display_order().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.bytes_in_display_order().encode_hex_upper() + } +} + +impl hex::FromHex for ConsensusBranchId { + type Error = <[u8; 4] as hex::FromHex>::Error; + + fn from_hex>(hex: T) -> Result { + let branch = <[u8; 4]>::from_hex(hex)?; + Ok(ConsensusBranchId(u32::from_be_bytes(branch))) + } +} + +impl fmt::Display for ConsensusBranchId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.encode_hex::()) + } +} + +/// A hex-encoded [`ConsensusBranchId`] string. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)] +pub struct ConsensusBranchIdHex(#[serde(with = "hex")] pub ConsensusBranchId); + +/// The activation status of a [`NetworkUpgrade`]. +#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum NetworkUpgradeStatus { + /// The network upgrade is currently active. + /// + /// Includes all network upgrades that have previously activated, + /// even if they are not the most recent network upgrade. + #[serde(rename = "active")] + Active, + + /// The network upgrade does not have an activation height. + #[serde(rename = "disabled")] + Disabled, + + /// The network upgrade has an activation height, but we haven't reached it yet. + #[serde(rename = "pending")] + Pending, +} + +/// A Zcash network upgrade. +/// +/// Network upgrades can change the Zcash network protocol or consensus rules in +/// incompatible ways. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum NetworkUpgrade { + /// The Zcash protocol for a Genesis block. + /// + /// Zcash genesis blocks use a different set of consensus rules from + /// other BeforeOverwinter blocks, so we treat them like a separate network + /// upgrade. + Genesis, + /// The Zcash protocol before the Overwinter upgrade. + /// + /// We avoid using `Sprout`, because the specification says that Sprout + /// is the name of the pre-Sapling protocol, before and after Overwinter. + BeforeOverwinter, + /// The Zcash protocol after the Overwinter upgrade. + Overwinter, + /// The Zcash protocol after the Sapling upgrade. + Sapling, + /// The Zcash protocol after the Blossom upgrade. + Blossom, + /// The Zcash protocol after the Heartwood upgrade. + Heartwood, + /// The Zcash protocol after the Canopy upgrade. + Canopy, + /// The Zcash protocol after the Nu5 upgrade. + /// + /// Note: Network Upgrade 5 includes the Orchard Shielded Protocol, non-malleable transaction + /// IDs, and other changes. There is no special code name for Nu5. + #[serde(rename = "NU5")] + Nu5, +} + +impl fmt::Display for NetworkUpgrade { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Same as the debug representation for now + fmt::Debug::fmt(self, f) + } +} + +/// Information about [`NetworkUpgrade`] activation. +#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct NetworkUpgradeInfo { + /// Name of upgrade, string. + pub name: NetworkUpgrade, + + /// Block height of activation, numeric. + #[serde(rename = "activationheight")] + pub activation_height: ChainHeight, + + /// Status of upgrade, string. + pub status: NetworkUpgradeStatus, +} + +/// The [`ConsensusBranchId`]s for the tip and the next block. +/// +/// These branch IDs are different when the next block is a network upgrade activation block. +#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct TipConsensusBranch { + /// Branch ID used to validate the current chain tip, big-endian, hex-encoded. + #[serde(rename = "chaintip")] + pub chain_tip: ConsensusBranchIdHex, + + /// Branch ID used to validate the next block, big-endian, hex-encoded. + #[serde(rename = "nextblock")] + pub next_block: ConsensusBranchIdHex, +} diff --git a/zingo-rpc/src/primitives/client.rs b/zingo-rpc/src/primitives/client.rs new file mode 100644 index 0000000..6ad8e7a --- /dev/null +++ b/zingo-rpc/src/primitives/client.rs @@ -0,0 +1,18 @@ +//! Holds primitive structs for ZingoProxy network clients. + +use nym_sdk::mixnet::MixnetClient; +use std::sync::{atomic::AtomicBool, Arc}; + +/// Configuration data for gRPC server. +pub struct ProxyClient { + /// Lightwalletd uri. + /// Used by grpc_passthrough to pass on unimplemented RPCs. + pub lightwalletd_uri: http::Uri, + /// Zebrad uri. + pub zebrad_uri: http::Uri, + /// Represents the Online status of the gRPC server. + pub online: Arc, +} + +/// Wrapper struct for a Nym client. +pub struct NymClient(pub MixnetClient); diff --git a/zingo-rpc/src/primitives/error.rs b/zingo-rpc/src/primitives/error.rs new file mode 100644 index 0000000..a6f4e73 --- /dev/null +++ b/zingo-rpc/src/primitives/error.rs @@ -0,0 +1,39 @@ +//! Hold error types for zingoProxy primitives and related functionality. + +/// A serialization error. +#[derive(thiserror::Error, Debug)] +pub enum SerializationError { + /// An io error that prevented deserialization + #[error("io error: {0}")] + Io(#[from] std::io::Error), + + /// The data to be deserialized was malformed. + // TODO: refine errors + #[error("parse error: {0}")] + Parse(&'static str), + + /// A string was not UTF-8. + /// + /// Note: Rust `String` and `str` are always UTF-8. + #[error("string was not UTF-8: {0}")] + Utf8Error(#[from] std::str::Utf8Error), + + /// A slice was an unexpected length during deserialization. + #[error("slice was the wrong length: {0}")] + TryFromSliceError(#[from] std::array::TryFromSliceError), + + /// The length of a vec is too large to convert to a usize (and thus, too large to allocate on this platform) + #[error("CompactSize too large: {0}")] + TryFromIntError(#[from] std::num::TryFromIntError), + + /// A string was not valid hexadecimal. + #[error("string was not hex: {0}")] + FromHexError(#[from] hex::FromHexError), +} + +/// Error type alias to make working with generic errors easier. +/// +/// Note: the 'static lifetime bound means that the *type* cannot have any +/// non-'static lifetimes, (e.g., when a type contains a borrow and is +/// parameterized by 'a), *not* that the object itself has 'static lifetime. +pub type BoxError = Box; diff --git a/zingo-rpc/src/primitives/height.rs b/zingo-rpc/src/primitives/height.rs new file mode 100644 index 0000000..9cca2cd --- /dev/null +++ b/zingo-rpc/src/primitives/height.rs @@ -0,0 +1,358 @@ +//! Blockheight, impl taken from zebra-chain for consistancy. + +use crate::primitives::error::{BoxError, SerializationError}; +use serde::{Deserialize, Serialize}; +use std::{ + fmt, + ops::{Add, Sub}, +}; +use thiserror::Error; + +/// A wrapper type representing blockchain heights. Safe conversion from +/// various integer types, as well as addition and subtraction, are provided. +/// +/// Taken from librustzcash::consensus. +#[repr(transparent)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct BlockHeight(u32); + +impl BlockHeight { + /// Tries to convert a u32 to a BlockHeight. + pub const fn from_u32(v: u32) -> BlockHeight { + BlockHeight(v) + } + + /// Subtracts the provided value from this height, returning `H0` if this would result in + /// underflow of the wrapped `u32`. + pub fn saturating_sub(self, v: u32) -> BlockHeight { + BlockHeight(self.0.saturating_sub(v)) + } +} + +impl fmt::Display for BlockHeight { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(formatter) + } +} + +impl From for BlockHeight { + fn from(value: u32) -> Self { + BlockHeight(value) + } +} + +impl From for u32 { + fn from(value: BlockHeight) -> u32 { + value.0 + } +} + +impl TryFrom for BlockHeight { + type Error = std::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + u32::try_from(value).map(BlockHeight) + } +} + +impl From for u64 { + fn from(value: BlockHeight) -> u64 { + value.0 as u64 + } +} + +impl TryFrom for BlockHeight { + type Error = std::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + u32::try_from(value).map(BlockHeight) + } +} + +impl TryFrom for BlockHeight { + type Error = std::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + u32::try_from(value).map(BlockHeight) + } +} + +impl From for i64 { + fn from(value: BlockHeight) -> i64 { + value.0 as i64 + } +} + +impl Add for BlockHeight { + type Output = Self; + + fn add(self, other: u32) -> Self { + BlockHeight(self.0 + other) + } +} + +impl Add for BlockHeight { + type Output = Self; + + fn add(self, other: Self) -> Self { + self + other.0 + } +} + +impl Sub for BlockHeight { + type Output = Self; + + fn sub(self, other: u32) -> Self { + if other > self.0 { + panic!("Subtraction resulted in negative block height."); + } + + BlockHeight(self.0 - other) + } +} + +impl Sub for BlockHeight { + type Output = Self; + + fn sub(self, other: Self) -> Self { + self - other.0 + } +} + +/// The length of the chain back to the genesis block. +/// +/// Two [`Height`]s can't be added, but they can be *subtracted* to get their difference, +/// represented as an [`HeightDiff`]. This difference can then be added to or subtracted from a +/// [`Height`]. Note the similarity with `chrono::DateTime` and `chrono::Duration`. +/// +/// # Invariants +/// +/// Users should not construct block heights greater than `Height::MAX`. +/// +/// # Consensus +/// +/// There are multiple formats for serializing a height, so we don't implement +/// `ZcashSerialize` or `ZcashDeserialize` for `Height`. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct ChainHeight(pub u32); + +/// Errors originating from ChainHeight calculations. +#[derive(Error, Debug)] +pub enum ChainHeightError { + /// Height overflow error. + #[error("The resulting height would overflow Height::MAX.")] + Overflow, + /// Height underflow error. + #[error("The resulting height would underflow Height::MIN.")] + Underflow, +} + +impl std::str::FromStr for ChainHeight { + type Err = SerializationError; + fn from_str(s: &str) -> Result { + match s.parse() { + Ok(h) if (ChainHeight(h) <= ChainHeight::MAX) => Ok(ChainHeight(h)), + Ok(_) => Err(SerializationError::Parse("Height exceeds maximum height")), + Err(_) => Err(SerializationError::Parse("Height(u32) integer parse error")), + } + } +} + +impl ChainHeight { + /// The minimum [`Height`]. + /// + /// Due to the underlying type, it is impossible to construct block heights + /// less than [`Height::MIN`]. + /// + /// Style note: Sometimes, [`Height::MIN`] is less readable than + /// `Height(0)`. Use whichever makes sense in context. + pub const MIN: ChainHeight = ChainHeight(0); + + /// The maximum [`Height`]. + /// + /// Users should not construct block heights greater than [`Height::MAX`]. + /// + /// The spec says *"Implementations MUST support block heights up to and + /// including 2^31 − 1"*. + /// + /// Note that `u32::MAX / 2 == 2^31 - 1 == i32::MAX`. + pub const MAX: ChainHeight = ChainHeight(u32::MAX / 2); + + /// The maximum [`Height`] as a [`u32`], for range patterns. + /// + /// `Height::MAX.0` can't be used in match range patterns, use this + /// alias instead. + pub const MAX_AS_U32: u32 = Self::MAX.0; + + /// The maximum expiration [`Height`] that is allowed in all transactions + /// previous to Nu5 and in non-coinbase transactions from Nu5 activation + /// height and above. + pub const MAX_EXPIRY_HEIGHT: ChainHeight = ChainHeight(499_999_999); + + /// Returns the next [`Height`]. + /// + /// # Panics + /// + /// - If the current height is at its maximum. + pub fn next(self) -> Result { + (self + 1).ok_or(ChainHeightError::Overflow) + } + + /// Returns the previous [`Height`]. + /// + /// # Panics + /// + /// - If the current height is at its minimum. + pub fn previous(self) -> Result { + (self - 1).ok_or(ChainHeightError::Underflow) + } + + /// Returns `true` if the [`Height`] is at its minimum. + pub fn is_min(self) -> bool { + self == Self::MIN + } + + /// Returns the value as a `usize`. + pub fn as_usize(self) -> usize { + self.0.try_into().expect("fits in usize") + } +} + +impl From for BlockHeight { + fn from(height: ChainHeight) -> Self { + BlockHeight::from_u32(height.0) + } +} + +impl TryFrom for ChainHeight { + type Error = &'static str; + + /// Checks that the `height` is within the valid [`Height`] range. + fn try_from(height: BlockHeight) -> Result { + Self::try_from(u32::from(height)) + } +} + +/// A difference between two [`Height`]s, possibly negative. +/// +/// This can represent the difference between any height values, +/// even if they are outside the valid height range (for example, in buggy RPC code). +pub type HeightDiff = i64; + +// We don't implement TryFrom, because it causes type inference issues for integer constants. +// Instead, use 1u64.try_into_height(). + +impl TryFrom for ChainHeight { + type Error = &'static str; + + /// Checks that the `height` is within the valid [`Height`] range. + fn try_from(height: u32) -> Result { + // Check the bounds. + // + // Clippy warns that `height >= Height::MIN.0` is always true. + assert_eq!(ChainHeight::MIN.0, 0); + + if height <= ChainHeight::MAX.0 { + Ok(ChainHeight(height)) + } else { + Err("heights must be less than or equal to Height::MAX") + } + } +} + +/// Convenience trait for converting a type into a valid Zcash [`Height`]. +pub trait TryIntoHeight { + /// The error type returned by [`Height`] conversion failures. + type Error; + + /// Convert `self` to a `Height`, if possible. + fn try_into_height(&self) -> Result; +} + +impl TryIntoHeight for u64 { + type Error = BoxError; + + fn try_into_height(&self) -> Result { + u32::try_from(*self)?.try_into().map_err(Into::into) + } +} + +impl TryIntoHeight for usize { + type Error = BoxError; + + fn try_into_height(&self) -> Result { + u32::try_from(*self)?.try_into().map_err(Into::into) + } +} + +impl TryIntoHeight for str { + type Error = BoxError; + + fn try_into_height(&self) -> Result { + self.parse().map_err(Into::into) + } +} + +impl TryIntoHeight for String { + type Error = BoxError; + + fn try_into_height(&self) -> Result { + self.as_str().try_into_height() + } +} + +impl TryIntoHeight for i32 { + type Error = BoxError; + + fn try_into_height(&self) -> Result { + u32::try_from(*self)?.try_into().map_err(Into::into) + } +} + +// We don't implement Add or Sub, because they cause type inference issues for integer constants. + +impl Sub for ChainHeight { + type Output = HeightDiff; + + /// Subtract two heights, returning the result, which can be negative. + /// Since [`HeightDiff`] is `i64` and [`Height`] is `u32`, the result is always correct. + fn sub(self, rhs: ChainHeight) -> Self::Output { + // All these conversions are exact, and the subtraction can't overflow or underflow. + let lhs = HeightDiff::from(self.0); + let rhs = HeightDiff::from(rhs.0); + + lhs - rhs + } +} + +impl Sub for ChainHeight { + type Output = Option; + + /// Subtract a height difference from a height, returning `None` if the resulting height is + /// outside the valid `Height` range (this also checks the result is non-negative). + fn sub(self, rhs: HeightDiff) -> Option { + // We need to convert the height to [`i64`] so we can subtract negative [`HeightDiff`]s. + let lhs = HeightDiff::from(self.0); + let res = lhs - rhs; + + // Check the bounds. + let res = u32::try_from(res).ok()?; + ChainHeight::try_from(res).ok() + } +} + +impl Add for ChainHeight { + type Output = Option; + + /// Add a height difference to a height, returning `None` if the resulting height is outside + /// the valid `Height` range (this also checks the result is non-negative). + fn add(self, rhs: HeightDiff) -> Option { + // We need to convert the height to [`i64`] so we can add negative [`HeightDiff`]s. + let lhs = i64::from(self.0); + let res = lhs + rhs; + + // Check the bounds. + let res = u32::try_from(res).ok()?; + ChainHeight::try_from(res).ok() + } +} diff --git a/zingo-rpc/src/primitives/transaction.rs b/zingo-rpc/src/primitives/transaction.rs new file mode 100644 index 0000000..7ec7634 --- /dev/null +++ b/zingo-rpc/src/primitives/transaction.rs @@ -0,0 +1,426 @@ +//! Hold primitives relating to zcash transactions. + +use std::fmt; + +use crate::primitives::{error::SerializationError, height::ChainHeight}; +use hex::ToHex; +use serde::ser::SerializeStruct; + +/// Zcash note commitment tree information. +#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct CommitmentTreeSize { + /// Commitment tree size. + pub size: u64, +} + +/// Information about the note commitment trees. +#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct BlockCommitmentTreeSize { + /// Sapling commitment tree size. + pub sapling: CommitmentTreeSize, + /// Orchard commitment tree size. + pub orchard: CommitmentTreeSize, +} + +/// Zingo-Proxy commitment tree structure replicating functionality in Zebra. +/// +/// A wrapper that contains either an Orchard or Sapling note commitment tree. +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct CommitmentTreestate { + /// Commitment tree state + pub final_state: String, +} + +/// Zingo-Proxy sapling treestate. +/// +/// A treestate that is included in the [`z_gettreestate`][1] RPC response. +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct SaplingTreestate { + /// Sapling note commitment tree. + pub commitments: CommitmentTreestate, +} + +/// Zingo-Proxy orchard treestate. +/// +/// A treestate that is included in the [`z_gettreestate`][1] RPC response. +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct OrchardTreestate { + /// Sapling note commitment tree. + pub commitments: CommitmentTreestate, +} + +/// A serialized transaction. +/// +/// Stores bytes that are guaranteed to be deserializable into a [`Transaction`]. +/// +/// Sorts in lexicographic order of the transaction's serialized data. +#[derive(Clone, Eq, PartialEq, serde::Serialize)] +pub struct SerializedTransaction { + /// Transaction bytes. + pub bytes: Vec, +} + +impl std::fmt::Display for SerializedTransaction { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(&hex::encode(&self.bytes)) + } +} + +impl std::fmt::Debug for SerializedTransaction { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let data_hex = hex::encode(&self.bytes); + + f.debug_tuple("ProxySerializedTransaction") + .field(&data_hex) + .finish() + } +} + +impl AsRef<[u8]> for SerializedTransaction { + fn as_ref(&self) -> &[u8] { + self.bytes.as_ref() + } +} + +impl From> for SerializedTransaction { + fn from(bytes: Vec) -> Self { + Self { bytes } + } +} + +impl hex::FromHex for SerializedTransaction { + type Error = as hex::FromHex>::Error; + + fn from_hex>(hex: T) -> Result { + let bytes = >::from_hex(hex)?; + + Ok(bytes.into()) + } +} + +impl<'de> serde::Deserialize<'de> for SerializedTransaction { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let v = serde_json::Value::deserialize(deserializer)?; + if let Some(hex_str) = v.as_str() { + let bytes = hex::decode(hex_str).map_err(serde::de::Error::custom)?; + Ok(SerializedTransaction { bytes }) + } else { + Err(serde::de::Error::custom("expected a hex string")) + } + } +} + +/// A transaction ID, which uniquely identifies mined v5 transactions, +/// and all v1-v4 transactions. +/// +/// Note: Zebra displays transaction and block hashes in big-endian byte-order, +/// following the u256 convention set by Bitcoin and zcashd. +/// +/// "The transaction ID of a version 4 or earlier transaction is the SHA-256d hash +/// of the transaction encoding in the pre-v5 format described above. +/// +/// The transaction ID of a version 5 transaction is as defined in [ZIP-244]." +/// [Spec: Transaction Identifiers] +/// +/// [ZIP-244]: https://zips.z.cash/zip-0244 +/// [Spec: Transaction Identifiers]: https://zips.z.cash/protocol/protocol.pdf#txnidentifiers +/// +/// Taken from zebra-chain for consistency +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize, serde::Deserialize, Hash, +)] +pub struct TransactionHash(pub [u8; 32]); + +impl From<[u8; 32]> for TransactionHash { + fn from(bytes: [u8; 32]) -> Self { + Self(bytes) + } +} + +impl From for [u8; 32] { + fn from(hash: TransactionHash) -> Self { + hash.0 + } +} + +impl From<&TransactionHash> for [u8; 32] { + fn from(hash: &TransactionHash) -> Self { + (*hash).into() + } +} + +impl TransactionHash { + /// Return the hash bytes in big-endian byte-order suitable for printing out byte by byte. + /// + /// Zebra displays transaction and block hashes in big-endian byte-order, + /// following the u256 convention set by Bitcoin and zcashd. + pub fn bytes_in_display_order(&self) -> [u8; 32] { + let mut reversed_bytes = self.0; + reversed_bytes.reverse(); + reversed_bytes + } + + /// Convert bytes in big-endian byte-order into a [`transaction::Hash`](crate::transaction::Hash). + /// + /// Zebra displays transaction and block hashes in big-endian byte-order, + /// following the u256 convention set by Bitcoin and zcashd. + pub fn from_bytes_in_display_order(bytes_in_display_order: &[u8; 32]) -> TransactionHash { + let mut internal_byte_order = *bytes_in_display_order; + internal_byte_order.reverse(); + + TransactionHash(internal_byte_order) + } +} + +impl ToHex for &TransactionHash { + fn encode_hex>(&self) -> T { + self.bytes_in_display_order().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.bytes_in_display_order().encode_hex_upper() + } +} + +impl ToHex for TransactionHash { + fn encode_hex>(&self) -> T { + (&self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + (&self).encode_hex_upper() + } +} + +impl hex::FromHex for TransactionHash { + type Error = <[u8; 32] as hex::FromHex>::Error; + + fn from_hex>(hex: T) -> Result { + let mut hash = <[u8; 32]>::from_hex(hex)?; + hash.reverse(); + + Ok(hash.into()) + } +} + +impl fmt::Display for TransactionHash { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.encode_hex::()) + } +} + +impl fmt::Debug for TransactionHash { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("transaction::Hash") + .field(&self.encode_hex::()) + .finish() + } +} + +impl std::str::FromStr for TransactionHash { + type Err = SerializationError; + + fn from_str(s: &str) -> Result { + let mut bytes = [0; 32]; + if hex::decode_to_slice(s, &mut bytes[..]).is_err() { + Err(SerializationError::Parse("hex decoding error")) + } else { + bytes.reverse(); + Ok(TransactionHash(bytes)) + } + } +} + +/// *** THE FOLLOWING CODE IS CURRENTLY UNUSED BY ZINGO-PROXY AND UNTESTED! *** +/// *** TEST BEFORE USE *** + +/// Wrapper type that can hold Sapling or Orchard subtree roots with hex encoding. +/// +/// *** UNTESTED - TEST BEFORE USE *** +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SubtreeRpcData { + /// Merkle root of the 2^16-leaf subtree. + pub root: String, + /// Height of the block containing the note that completed this subtree. + pub height: ChainHeight, +} + +impl SubtreeRpcData { + /// Returns new instance of ProxySubtreeRpcData + pub fn new(root: String, height: ChainHeight) -> Self { + Self { root, height } + } +} + +impl serde::Serialize for SubtreeRpcData { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_struct("ProxySubtreeRpcData", 2)?; + state.serialize_field("root", &self.root)?; + state.serialize_field("height", &self.height)?; + state.end() + } +} + +impl<'de> serde::Deserialize<'de> for SubtreeRpcData { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(serde::Deserialize)] + struct Inner { + root: String, + height: ChainHeight, + } + + let inner = Inner::deserialize(deserializer)?; + Ok(SubtreeRpcData { + root: inner.root, + height: inner.height, + }) + } +} + +impl hex::FromHex for SubtreeRpcData { + type Error = hex::FromHexError; + + fn from_hex>(hex: T) -> Result { + let hex_str = std::str::from_utf8(hex.as_ref()) + .map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?; + + if hex_str.len() < 8 { + return Err(hex::FromHexError::OddLength); + } + + let root_end_index = hex_str.len() - 8; + let (root_hex, height_hex) = hex_str.split_at(root_end_index); + + let root = root_hex.to_string(); + let height = u32::from_str_radix(height_hex, 16) + .map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?; + + Ok(SubtreeRpcData { + root, + height: ChainHeight(height), + }) + } +} + +/// Zingo-Proxy encoding of a Bitcoin script. +/// +/// *** UNTESTED - TEST BEFORE USE *** +#[derive(Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct ZcashScript { + /// # Correctness + /// + /// Consensus-critical serialization uses [`ZcashSerialize`]. + /// [`serde`]-based hex serialization must only be used for RPCs and testing. + #[serde(with = "hex")] + pub script: Vec, +} + +impl ZcashScript { + /// Create a new Bitcoin script from its raw bytes. + /// The raw bytes must not contain the length prefix. + pub fn new(raw_bytes: &[u8]) -> Self { + Self { + script: raw_bytes.to_vec(), + } + } + + /// Return the raw bytes of the script without the length prefix. + /// + /// # Correctness + /// + /// These raw bytes do not have a length prefix. + /// The Zcash serialization format requires a length prefix; use `zcash_serialize` + /// and `zcash_deserialize` to create byte data with a length prefix. + pub fn as_raw_bytes(&self) -> &[u8] { + &self.script + } +} + +impl core::fmt::Display for ZcashScript { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_str(&self.encode_hex::()) + } +} + +impl core::fmt::Debug for ZcashScript { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_tuple("Script") + .field(&hex::encode(&self.script)) + .finish() + } +} + +impl hex::ToHex for &ZcashScript { + fn encode_hex>(&self) -> T { + self.as_raw_bytes().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.as_raw_bytes().encode_hex_upper() + } +} + +impl hex::ToHex for ZcashScript { + fn encode_hex>(&self) -> T { + (&self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + (&self).encode_hex_upper() + } +} + +impl hex::FromHex for ZcashScript { + type Error = hex::FromHexError; + + fn from_hex>(hex: T) -> Result { + let bytes = Vec::from_hex(hex)?; + Ok(Self { script: bytes }) + } +} + +/// A note commitment subtree index, used to identify a subtree in a shielded pool. +/// Also used to count subtrees. +/// +/// *** UNTESTED - TEST BEFORE USE *** +#[derive( + Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, serde::Serialize, serde::Deserialize, +)] +pub struct NoteCommitmentSubtreeIndex(pub u16); + +impl fmt::Display for NoteCommitmentSubtreeIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0.to_string()) + } +} + +impl From for NoteCommitmentSubtreeIndex { + fn from(value: u16) -> Self { + Self(value) + } +} + +impl TryFrom for NoteCommitmentSubtreeIndex { + type Error = std::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + u16::try_from(value).map(Self) + } +} + +// If we want to automatically convert NoteCommitmentSubtreeIndex to the generic integer literal +// type, we can only implement conversion into u64. (Or u16, but not both.) +impl From for u64 { + fn from(value: NoteCommitmentSubtreeIndex) -> Self { + value.0.into() + } +} diff --git a/zingo-rpc/src/proto.rs b/zingo-rpc/src/proto.rs new file mode 100644 index 0000000..055904d --- /dev/null +++ b/zingo-rpc/src/proto.rs @@ -0,0 +1,7 @@ +//! Holds tonic generated code for the lightwallet service RPCs and compact formats. + +#![allow(missing_docs)] + +pub mod compact_formats; +pub mod proposal; +pub mod service; diff --git a/zingo-rpc/src/proto/compact_formats.rs b/zingo-rpc/src/proto/compact_formats.rs new file mode 100644 index 0000000..4445537 --- /dev/null +++ b/zingo-rpc/src/proto/compact_formats.rs @@ -0,0 +1,122 @@ +/// Information about the state of the chain as of a given block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChainMetadata { + /// the size of the Sapling note commitment tree as of the end of this block + #[prost(uint32, tag = "1")] + pub sapling_commitment_tree_size: u32, + /// the size of the Orchard note commitment tree as of the end of this block + #[prost(uint32, tag = "2")] + pub orchard_commitment_tree_size: u32, +} +/// A compact representation of the shielded data in a Zcash block. +/// +/// CompactBlock is a packaging of ONLY the data from a block that's needed to: +/// 1. Detect a payment to your shielded Sapling address +/// 2. Detect a spend of your shielded Sapling notes +/// 3. Update your witnesses to generate new Sapling spend proofs. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompactBlock { + /// the version of this wire format, for storage + #[prost(uint32, tag = "1")] + pub proto_version: u32, + /// the height of this block + #[prost(uint64, tag = "2")] + pub height: u64, + /// the ID (hash) of this block, same as in block explorers + #[prost(bytes = "vec", tag = "3")] + pub hash: ::prost::alloc::vec::Vec, + /// the ID (hash) of this block's predecessor + #[prost(bytes = "vec", tag = "4")] + pub prev_hash: ::prost::alloc::vec::Vec, + /// Unix epoch time when the block was mined + #[prost(uint32, tag = "5")] + pub time: u32, + /// (hash, prevHash, and time) OR (full header) + #[prost(bytes = "vec", tag = "6")] + pub header: ::prost::alloc::vec::Vec, + /// zero or more compact transactions from this block + #[prost(message, repeated, tag = "7")] + pub vtx: ::prost::alloc::vec::Vec, + /// information about the state of the chain as of this block + #[prost(message, optional, tag = "8")] + pub chain_metadata: ::core::option::Option, +} +/// A compact representation of the shielded data in a Zcash transaction. +/// +/// CompactTx contains the minimum information for a wallet to know if this transaction +/// is relevant to it (either pays to it or spends from it) via shielded elements +/// only. This message will not encode a transparent-to-transparent transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompactTx { + /// Index and hash will allow the receiver to call out to chain + /// explorers or other data structures to retrieve more information + /// about this transaction. + /// + /// the index within the full block + #[prost(uint64, tag = "1")] + pub index: u64, + /// the ID (hash) of this transaction, same as in block explorers + #[prost(bytes = "vec", tag = "2")] + pub hash: ::prost::alloc::vec::Vec, + /// The transaction fee: present if server can provide. In the case of a + /// stateless server and a transaction with transparent inputs, this will be + /// unset because the calculation requires reference to prior transactions. + /// If there are no transparent inputs, the fee will be calculable as: + /// valueBalanceSapling + valueBalanceOrchard + sum(vPubNew) - sum(vPubOld) - sum(tOut) + #[prost(uint32, tag = "3")] + pub fee: u32, + #[prost(message, repeated, tag = "4")] + pub spends: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "5")] + pub outputs: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "6")] + pub actions: ::prost::alloc::vec::Vec, +} +/// A compact representation of a [Sapling Spend](). +/// +/// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash +/// protocol specification. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompactSaplingSpend { + /// Nullifier (see the Zcash protocol specification) + #[prost(bytes = "vec", tag = "1")] + pub nf: ::prost::alloc::vec::Vec, +} +/// A compact representation of a [Sapling Output](). +/// +/// It encodes the `cmu` field, `ephemeralKey` field, and a 52-byte prefix of the +/// `encCiphertext` field of a Sapling Output Description. Total size is 116 bytes. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompactSaplingOutput { + /// Note commitment u-coordinate. + #[prost(bytes = "vec", tag = "1")] + pub cmu: ::prost::alloc::vec::Vec, + /// Ephemeral public key. + #[prost(bytes = "vec", tag = "2")] + pub ephemeral_key: ::prost::alloc::vec::Vec, + /// First 52 bytes of ciphertext. + #[prost(bytes = "vec", tag = "3")] + pub ciphertext: ::prost::alloc::vec::Vec, +} +/// A compact representation of an [Orchard Action](). +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompactOrchardAction { + /// \[32\] The nullifier of the input note + #[prost(bytes = "vec", tag = "1")] + pub nullifier: ::prost::alloc::vec::Vec, + /// \[32\] The x-coordinate of the note commitment for the output note + #[prost(bytes = "vec", tag = "2")] + pub cmx: ::prost::alloc::vec::Vec, + /// \[32\] An encoding of an ephemeral Pallas public key + #[prost(bytes = "vec", tag = "3")] + pub ephemeral_key: ::prost::alloc::vec::Vec, + /// \[52\] The first 52 bytes of the encCiphertext field + #[prost(bytes = "vec", tag = "4")] + pub ciphertext: ::prost::alloc::vec::Vec, +} diff --git a/zingo-rpc/src/proto/proposal.rs b/zingo-rpc/src/proto/proposal.rs new file mode 100644 index 0000000..1ea321a --- /dev/null +++ b/zingo-rpc/src/proto/proposal.rs @@ -0,0 +1,235 @@ +/// A data structure that describes a series of transactions to be created. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Proposal { + /// The version of this serialization format. + #[prost(uint32, tag = "1")] + pub proto_version: u32, + /// The fee rule used in constructing this proposal + #[prost(enumeration = "FeeRule", tag = "2")] + pub fee_rule: i32, + /// The target height for which the proposal was constructed + /// + /// The chain must contain at least this many blocks in order for the proposal to + /// be executed. + #[prost(uint32, tag = "3")] + pub min_target_height: u32, + /// The series of transactions to be created. + #[prost(message, repeated, tag = "4")] + pub steps: ::prost::alloc::vec::Vec, +} +/// A data structure that describes the inputs to be consumed and outputs to +/// be produced in a proposed transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProposalStep { + /// ZIP 321 serialized transaction request + #[prost(string, tag = "1")] + pub transaction_request: ::prost::alloc::string::String, + /// The vector of selected payment index / output pool mappings. Payment index + /// 0 corresponds to the payment with no explicit index. + #[prost(message, repeated, tag = "2")] + pub payment_output_pools: ::prost::alloc::vec::Vec, + /// The anchor height to be used in creating the transaction, if any. + /// Setting the anchor height to zero will disallow the use of any shielded + /// inputs. + #[prost(uint32, tag = "3")] + pub anchor_height: u32, + /// The inputs to be used in creating the transaction. + #[prost(message, repeated, tag = "4")] + pub inputs: ::prost::alloc::vec::Vec, + /// The total value, fee value, and change outputs of the proposed + /// transaction + #[prost(message, optional, tag = "5")] + pub balance: ::core::option::Option, + /// A flag indicating whether the step is for a shielding transaction, + /// used for determining which OVK to select for wallet-internal outputs. + #[prost(bool, tag = "6")] + pub is_shielding: bool, +} +/// A mapping from ZIP 321 payment index to the output pool that has been chosen +/// for that payment, based upon the payment address and the selected inputs to +/// the transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PaymentOutputPool { + #[prost(uint32, tag = "1")] + pub payment_index: u32, + #[prost(enumeration = "ValuePool", tag = "2")] + pub value_pool: i32, +} +/// The unique identifier and value for each proposed input that does not +/// require a back-reference to a prior step of the proposal. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReceivedOutput { + #[prost(bytes = "vec", tag = "1")] + pub txid: ::prost::alloc::vec::Vec, + #[prost(enumeration = "ValuePool", tag = "2")] + pub value_pool: i32, + #[prost(uint32, tag = "3")] + pub index: u32, + #[prost(uint64, tag = "4")] + pub value: u64, +} +/// A reference to a payment in a prior step of the proposal. This payment must +/// belong to the wallet. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PriorStepOutput { + #[prost(uint32, tag = "1")] + pub step_index: u32, + #[prost(uint32, tag = "2")] + pub payment_index: u32, +} +/// A reference to a change or ephemeral output from a prior step of the proposal. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PriorStepChange { + #[prost(uint32, tag = "1")] + pub step_index: u32, + #[prost(uint32, tag = "2")] + pub change_index: u32, +} +/// The unique identifier and value for an input to be used in the transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProposedInput { + #[prost(oneof = "proposed_input::Value", tags = "1, 2, 3")] + pub value: ::core::option::Option, +} +/// Nested message and enum types in `ProposedInput`. +pub mod proposed_input { + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Value { + #[prost(message, tag = "1")] + ReceivedOutput(super::ReceivedOutput), + #[prost(message, tag = "2")] + PriorStepOutput(super::PriorStepOutput), + #[prost(message, tag = "3")] + PriorStepChange(super::PriorStepChange), + } +} +/// The proposed change outputs and fee value. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionBalance { + /// A list of change or ephemeral output values. + #[prost(message, repeated, tag = "1")] + pub proposed_change: ::prost::alloc::vec::Vec, + /// The fee to be paid by the proposed transaction, in zatoshis. + #[prost(uint64, tag = "2")] + pub fee_required: u64, +} +/// A proposed change or ephemeral output. If the transparent value pool is +/// selected, the `memo` field must be null. +/// +/// When the `isEphemeral` field of a `ChangeValue` is set, it represents +/// an ephemeral output, which must be spent by a subsequent step. This is +/// only supported for transparent outputs. Each ephemeral output will be +/// given a unique t-address. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChangeValue { + /// The value of a change or ephemeral output to be created, in zatoshis. + #[prost(uint64, tag = "1")] + pub value: u64, + /// The value pool in which the change or ephemeral output should be created. + #[prost(enumeration = "ValuePool", tag = "2")] + pub value_pool: i32, + /// The optional memo that should be associated with the newly created output. + /// Memos must not be present for transparent outputs. + #[prost(message, optional, tag = "3")] + pub memo: ::core::option::Option, + /// Whether this is to be an ephemeral output. + #[prost(bool, tag = "4")] + pub is_ephemeral: bool, +} +/// An object wrapper for memo bytes, to facilitate representing the +/// `change_memo == None` case. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MemoBytes { + #[prost(bytes = "vec", tag = "1")] + pub value: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ValuePool { + /// Protobuf requires that enums have a zero discriminant as the default + /// value. However, we need to require that a known value pool is selected, + /// and we do not want to fall back to any default, so sending the + /// PoolNotSpecified value will be treated as an error. + PoolNotSpecified = 0, + /// The transparent value pool (P2SH is not distinguished from P2PKH) + Transparent = 1, + /// The Sapling value pool + Sapling = 2, + /// The Orchard value pool + Orchard = 3, +} +impl ValuePool { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ValuePool::PoolNotSpecified => "PoolNotSpecified", + ValuePool::Transparent => "Transparent", + ValuePool::Sapling => "Sapling", + ValuePool::Orchard => "Orchard", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "PoolNotSpecified" => Some(Self::PoolNotSpecified), + "Transparent" => Some(Self::Transparent), + "Sapling" => Some(Self::Sapling), + "Orchard" => Some(Self::Orchard), + _ => None, + } + } +} +/// The fee rule used in constructing a Proposal +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FeeRule { + /// Protobuf requires that enums have a zero discriminant as the default + /// value. However, we need to require that a known fee rule is selected, + /// and we do not want to fall back to any default, so sending the + /// FeeRuleNotSpecified value will be treated as an error. + NotSpecified = 0, + /// 10000 ZAT + PreZip313 = 1, + /// 1000 ZAT + Zip313 = 2, + /// MAX(10000, 5000 * logical_actions) ZAT + Zip317 = 3, +} +impl FeeRule { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FeeRule::NotSpecified => "FeeRuleNotSpecified", + FeeRule::PreZip313 => "PreZip313", + FeeRule::Zip313 => "Zip313", + FeeRule::Zip317 => "Zip317", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FeeRuleNotSpecified" => Some(Self::NotSpecified), + "PreZip313" => Some(Self::PreZip313), + "Zip313" => Some(Self::Zip313), + "Zip317" => Some(Self::Zip317), + _ => None, + } + } +} diff --git a/zingo-rpc/src/proto/service.rs b/zingo-rpc/src/proto/service.rs new file mode 100644 index 0000000..2a8dc3e --- /dev/null +++ b/zingo-rpc/src/proto/service.rs @@ -0,0 +1,2166 @@ +/// A BlockID message contains identifiers to select a block: a height or a +/// hash. Specification by hash is not implemented, but may be in the future. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockId { + #[prost(uint64, tag = "1")] + pub height: u64, + #[prost(bytes = "vec", tag = "2")] + pub hash: ::prost::alloc::vec::Vec, +} +/// BlockRange specifies a series of blocks from start to end inclusive. +/// Both BlockIDs must be heights; specification by hash is not yet supported. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockRange { + #[prost(message, optional, tag = "1")] + pub start: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub end: ::core::option::Option, +} +/// A TxFilter contains the information needed to identify a particular +/// transaction: either a block and an index, or a direct transaction hash. +/// Currently, only specification by hash is supported. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TxFilter { + /// block identifier, height or hash + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, + /// index within the block + #[prost(uint64, tag = "2")] + pub index: u64, + /// transaction ID (hash, txid) + #[prost(bytes = "vec", tag = "3")] + pub hash: ::prost::alloc::vec::Vec, +} +/// RawTransaction contains the complete transaction data. It also optionally includes +/// the block height in which the transaction was included, or, when returned +/// by GetMempoolStream(), the latest block height. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawTransaction { + /// exact data returned by Zcash 'getrawtransaction' + #[prost(bytes = "vec", tag = "1")] + pub data: ::prost::alloc::vec::Vec, + /// height that the transaction was mined (or -1) + #[prost(uint64, tag = "2")] + pub height: u64, +} +/// A SendResponse encodes an error code and a string. It is currently used +/// only by SendTransaction(). If error code is zero, the operation was +/// successful; if non-zero, it and the message specify the failure. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SendResponse { + #[prost(int32, tag = "1")] + pub error_code: i32, + #[prost(string, tag = "2")] + pub error_message: ::prost::alloc::string::String, +} +/// Chainspec is a placeholder to allow specification of a particular chain fork. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChainSpec {} +/// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Empty {} +/// LightdInfo returns various information about this lightwalletd instance +/// and the state of the blockchain. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightdInfo { + #[prost(string, tag = "1")] + pub version: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub vendor: ::prost::alloc::string::String, + /// true + #[prost(bool, tag = "3")] + pub taddr_support: bool, + /// either "main" or "test" + #[prost(string, tag = "4")] + pub chain_name: ::prost::alloc::string::String, + /// depends on mainnet or testnet + #[prost(uint64, tag = "5")] + pub sapling_activation_height: u64, + /// protocol identifier, see consensus/upgrades.cpp + #[prost(string, tag = "6")] + pub consensus_branch_id: ::prost::alloc::string::String, + /// latest block on the best chain + #[prost(uint64, tag = "7")] + pub block_height: u64, + #[prost(string, tag = "8")] + pub git_commit: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub branch: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub build_date: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub build_user: ::prost::alloc::string::String, + /// less than tip height if zcashd is syncing + #[prost(uint64, tag = "12")] + pub estimated_height: u64, + /// example: "v4.1.1-877212414" + #[prost(string, tag = "13")] + pub zcashd_build: ::prost::alloc::string::String, + /// example: "/MagicBean:4.1.1/" + #[prost(string, tag = "14")] + pub zcashd_subversion: ::prost::alloc::string::String, +} +/// TransparentAddressBlockFilter restricts the results to the given address +/// or block range. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransparentAddressBlockFilter { + /// t-address + #[prost(string, tag = "1")] + pub address: ::prost::alloc::string::String, + /// start, end heights + #[prost(message, optional, tag = "2")] + pub range: ::core::option::Option, +} +/// Duration is currently used only for testing, so that the Ping rpc +/// can simulate a delay, to create many simultaneous connections. Units +/// are microseconds. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Duration { + #[prost(int64, tag = "1")] + pub interval_us: i64, +} +/// PingResponse is used to indicate concurrency, how many Ping rpcs +/// are executing upon entry and upon exit (after the delay). +/// This rpc is used for testing only. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PingResponse { + #[prost(int64, tag = "1")] + pub entry: i64, + #[prost(int64, tag = "2")] + pub exit: i64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Address { + #[prost(string, tag = "1")] + pub address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AddressList { + #[prost(string, repeated, tag = "1")] + pub addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Balance { + #[prost(int64, tag = "1")] + pub value_zat: i64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Exclude { + #[prost(bytes = "vec", repeated, tag = "1")] + pub txid: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, +} +/// The TreeState is derived from the Zcash z_gettreestate rpc. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TreeState { + /// "main" or "test" + #[prost(string, tag = "1")] + pub network: ::prost::alloc::string::String, + /// block height + #[prost(uint64, tag = "2")] + pub height: u64, + /// block id + #[prost(string, tag = "3")] + pub hash: ::prost::alloc::string::String, + /// Unix epoch time when the block was mined + #[prost(uint32, tag = "4")] + pub time: u32, + /// sapling commitment tree state + #[prost(string, tag = "5")] + pub sapling_tree: ::prost::alloc::string::String, + /// orchard commitment tree state + #[prost(string, tag = "6")] + pub orchard_tree: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetSubtreeRootsArg { + /// Index identifying where to start returning subtree roots + #[prost(uint32, tag = "1")] + pub start_index: u32, + /// Shielded protocol to return subtree roots for + #[prost(enumeration = "ShieldedProtocol", tag = "2")] + pub shielded_protocol: i32, + /// Maximum number of entries to return, or 0 for all entries. + #[prost(uint32, tag = "3")] + pub max_entries: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubtreeRoot { + /// The 32-byte Merkle root of the subtree. + #[prost(bytes = "vec", tag = "2")] + pub root_hash: ::prost::alloc::vec::Vec, + /// The hash of the block that completed this subtree. + #[prost(bytes = "vec", tag = "3")] + pub completing_block_hash: ::prost::alloc::vec::Vec, + /// The height of the block that completed this subtree in the main chain. + #[prost(uint64, tag = "4")] + pub completing_block_height: u64, +} +/// Results are sorted by height, which makes it easy to issue another +/// request that picks up from where the previous left off. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosArg { + #[prost(string, repeated, tag = "1")] + pub addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint64, tag = "2")] + pub start_height: u64, + /// zero means unlimited + #[prost(uint32, tag = "3")] + pub max_entries: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosReply { + #[prost(string, tag = "6")] + pub address: ::prost::alloc::string::String, + #[prost(bytes = "vec", tag = "1")] + pub txid: ::prost::alloc::vec::Vec, + #[prost(int32, tag = "2")] + pub index: i32, + #[prost(bytes = "vec", tag = "3")] + pub script: ::prost::alloc::vec::Vec, + #[prost(int64, tag = "4")] + pub value_zat: i64, + #[prost(uint64, tag = "5")] + pub height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosReplyList { + #[prost(message, repeated, tag = "1")] + pub address_utxos: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ShieldedProtocol { + Sapling = 0, + Orchard = 1, +} +impl ShieldedProtocol { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ShieldedProtocol::Sapling => "sapling", + ShieldedProtocol::Orchard => "orchard", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "sapling" => Some(Self::Sapling), + "orchard" => Some(Self::Orchard), + _ => None, + } + } +} +/// Generated client implementations. +pub mod compact_tx_streamer_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct CompactTxStreamerClient { + inner: tonic::client::Grpc, + } + impl CompactTxStreamerClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl CompactTxStreamerClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> CompactTxStreamerClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + CompactTxStreamerClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Return the height of the tip of the best chain + pub async fn get_latest_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetLatestBlock", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Return the compact block corresponding to the given block identifier + pub async fn get_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlock", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Same as GetBlock except actions contain only nullifiers + pub async fn get_block_nullifiers( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockNullifiers", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlockNullifiers", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Return a list of consecutive compact blocks + pub async fn get_block_range( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlockRange", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// Same as GetBlockRange except actions contain only nullifiers + pub async fn get_block_range_nullifiers( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRangeNullifiers", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlockRangeNullifiers", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// Return the requested full (not compact) transaction (as from zcashd) + pub async fn get_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTransaction", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Submit the given transaction to the Zcash network + pub async fn send_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "SendTransaction", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Return the txids corresponding to the given t-address within the given block range + pub async fn get_taddress_txids( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressTxids", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + pub async fn get_taddress_balance( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressBalance", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_taddress_balance_stream( + &mut self, + request: impl tonic::IntoStreamingRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressBalanceStream", + ), + ); + self.inner.client_streaming(req, path, codec).await + } + /// Return the compact transactions currently in the mempool; the results + /// can be a few seconds out of date. If the Exclude list is empty, return + /// all transactions; otherwise return all *except* those in the Exclude list + /// (if any); this allows the client to avoid receiving transactions that it + /// already has (from an earlier call to this rpc). The transaction IDs in the + /// Exclude list can be shortened to any number of bytes to make the request + /// more bandwidth-efficient; if two or more transactions in the mempool + /// match a shortened txid, they are all sent (none is excluded). Transactions + /// in the exclude list that don't exist in the mempool are ignored. + pub async fn get_mempool_tx( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetMempoolTx", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// Return a stream of current Mempool transactions. This will keep the output stream open while + /// there are mempool transactions. It will close the returned stream when a new block is mined. + pub async fn get_mempool_stream( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetMempoolStream", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// GetTreeState returns the note commitment tree state corresponding to the given block. + /// See section 3.7 of the Zcash protocol specification. It returns several other useful + /// values also (even though they can be obtained using GetBlock). + /// The block can be specified by either height or hash. + pub async fn get_tree_state( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTreeState", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_latest_tree_state( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestTreeState", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetLatestTreeState", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Returns a stream of information about roots of subtrees of the Sapling and Orchard + /// note commitment trees. + pub async fn get_subtree_roots( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetSubtreeRoots", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetSubtreeRoots", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + pub async fn get_address_utxos( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetAddressUtxos", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_address_utxos_stream( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetAddressUtxosStream", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// Return information about this lightwalletd instance and the blockchain + pub async fn get_lightd_info( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetLightdInfo", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) + pub async fn ping( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("cash.z.wallet.sdk.rpc.CompactTxStreamer", "Ping"), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod compact_tx_streamer_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with CompactTxStreamerServer. + #[async_trait] + pub trait CompactTxStreamer: Send + Sync + 'static { + /// Return the height of the tip of the best chain + async fn get_latest_block( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Return the compact block corresponding to the given block identifier + async fn get_block( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Same as GetBlock except actions contain only nullifiers + async fn get_block_nullifiers( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the GetBlockRange method. + type GetBlockRangeStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + crate::proto::compact_formats::CompactBlock, + tonic::Status, + >, + > + + Send + + 'static; + /// Return a list of consecutive compact blocks + async fn get_block_range( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the GetBlockRangeNullifiers method. + type GetBlockRangeNullifiersStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + crate::proto::compact_formats::CompactBlock, + tonic::Status, + >, + > + + Send + + 'static; + /// Same as GetBlockRange except actions contain only nullifiers + async fn get_block_range_nullifiers( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Return the requested full (not compact) transaction (as from zcashd) + async fn get_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Submit the given transaction to the Zcash network + async fn send_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Server streaming response type for the GetTaddressTxids method. + type GetTaddressTxidsStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// Return the txids corresponding to the given t-address within the given block range + async fn get_taddress_txids( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_taddress_balance( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_taddress_balance_stream( + &self, + request: tonic::Request>, + ) -> std::result::Result, tonic::Status>; + /// Server streaming response type for the GetMempoolTx method. + type GetMempoolTxStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + crate::proto::compact_formats::CompactTx, + tonic::Status, + >, + > + + Send + + 'static; + /// Return the compact transactions currently in the mempool; the results + /// can be a few seconds out of date. If the Exclude list is empty, return + /// all transactions; otherwise return all *except* those in the Exclude list + /// (if any); this allows the client to avoid receiving transactions that it + /// already has (from an earlier call to this rpc). The transaction IDs in the + /// Exclude list can be shortened to any number of bytes to make the request + /// more bandwidth-efficient; if two or more transactions in the mempool + /// match a shortened txid, they are all sent (none is excluded). Transactions + /// in the exclude list that don't exist in the mempool are ignored. + async fn get_mempool_tx( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the GetMempoolStream method. + type GetMempoolStreamStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// Return a stream of current Mempool transactions. This will keep the output stream open while + /// there are mempool transactions. It will close the returned stream when a new block is mined. + async fn get_mempool_stream( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// GetTreeState returns the note commitment tree state corresponding to the given block. + /// See section 3.7 of the Zcash protocol specification. It returns several other useful + /// values also (even though they can be obtained using GetBlock). + /// The block can be specified by either height or hash. + async fn get_tree_state( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_latest_tree_state( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Server streaming response type for the GetSubtreeRoots method. + type GetSubtreeRootsStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// Returns a stream of information about roots of subtrees of the Sapling and Orchard + /// note commitment trees. + async fn get_subtree_roots( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_address_utxos( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the GetAddressUtxosStream method. + type GetAddressUtxosStreamStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + async fn get_address_utxos_stream( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Return information about this lightwalletd instance and the blockchain + async fn get_lightd_info( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) + async fn ping( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + } + #[derive(Debug)] + pub struct CompactTxStreamerServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl CompactTxStreamerServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for CompactTxStreamerServer + where + T: CompactTxStreamer, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock" => { + #[allow(non_camel_case_types)] + struct GetLatestBlockSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetLatestBlockSvc { + type Response = super::BlockId; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_latest_block(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetLatestBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock" => { + #[allow(non_camel_case_types)] + struct GetBlockSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService for GetBlockSvc { + type Response = crate::proto::compact_formats::CompactBlock; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_block(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockNullifiers" => { + #[allow(non_camel_case_types)] + struct GetBlockNullifiersSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetBlockNullifiersSvc { + type Response = crate::proto::compact_formats::CompactBlock; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_block_nullifiers( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetBlockNullifiersSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange" => { + #[allow(non_camel_case_types)] + struct GetBlockRangeSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetBlockRangeSvc { + type Response = crate::proto::compact_formats::CompactBlock; + type ResponseStream = T::GetBlockRangeStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_block_range(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetBlockRangeSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRangeNullifiers" => { + #[allow(non_camel_case_types)] + struct GetBlockRangeNullifiersSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetBlockRangeNullifiersSvc { + type Response = crate::proto::compact_formats::CompactBlock; + type ResponseStream = T::GetBlockRangeNullifiersStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_block_range_nullifiers( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetBlockRangeNullifiersSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction" => { + #[allow(non_camel_case_types)] + struct GetTransactionSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetTransactionSvc { + type Response = super::RawTransaction; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_transaction(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetTransactionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction" => { + #[allow(non_camel_case_types)] + struct SendTransactionSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for SendTransactionSvc { + type Response = super::SendResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::send_transaction(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = SendTransactionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids" => { + #[allow(non_camel_case_types)] + struct GetTaddressTxidsSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService< + super::TransparentAddressBlockFilter, + > for GetTaddressTxidsSvc { + type Response = super::RawTransaction; + type ResponseStream = T::GetTaddressTxidsStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_taddress_txids( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetTaddressTxidsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance" => { + #[allow(non_camel_case_types)] + struct GetTaddressBalanceSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetTaddressBalanceSvc { + type Response = super::Balance; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_taddress_balance( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetTaddressBalanceSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream" => { + #[allow(non_camel_case_types)] + struct GetTaddressBalanceStreamSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ClientStreamingService + for GetTaddressBalanceStreamSvc { + type Response = super::Balance; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request>, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_taddress_balance_stream( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetTaddressBalanceStreamSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.client_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx" => { + #[allow(non_camel_case_types)] + struct GetMempoolTxSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetMempoolTxSvc { + type Response = crate::proto::compact_formats::CompactTx; + type ResponseStream = T::GetMempoolTxStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_mempool_tx(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetMempoolTxSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream" => { + #[allow(non_camel_case_types)] + struct GetMempoolStreamSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetMempoolStreamSvc { + type Response = super::RawTransaction; + type ResponseStream = T::GetMempoolStreamStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_mempool_stream( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetMempoolStreamSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState" => { + #[allow(non_camel_case_types)] + struct GetTreeStateSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetTreeStateSvc { + type Response = super::TreeState; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_tree_state(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetTreeStateSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestTreeState" => { + #[allow(non_camel_case_types)] + struct GetLatestTreeStateSvc(pub Arc); + impl tonic::server::UnaryService + for GetLatestTreeStateSvc { + type Response = super::TreeState; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_latest_tree_state( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetLatestTreeStateSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetSubtreeRoots" => { + #[allow(non_camel_case_types)] + struct GetSubtreeRootsSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetSubtreeRootsSvc { + type Response = super::SubtreeRoot; + type ResponseStream = T::GetSubtreeRootsStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_subtree_roots(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetSubtreeRootsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos" => { + #[allow(non_camel_case_types)] + struct GetAddressUtxosSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService + for GetAddressUtxosSvc { + type Response = super::GetAddressUtxosReplyList; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_address_utxos(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetAddressUtxosSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream" => { + #[allow(non_camel_case_types)] + struct GetAddressUtxosStreamSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::ServerStreamingService + for GetAddressUtxosStreamSvc { + type Response = super::GetAddressUtxosReply; + type ResponseStream = T::GetAddressUtxosStreamStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_address_utxos_stream( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetAddressUtxosStreamSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo" => { + #[allow(non_camel_case_types)] + struct GetLightdInfoSvc(pub Arc); + impl tonic::server::UnaryService + for GetLightdInfoSvc { + type Response = super::LightdInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_lightd_info(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetLightdInfoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping" => { + #[allow(non_camel_case_types)] + struct PingSvc(pub Arc); + impl< + T: CompactTxStreamer, + > tonic::server::UnaryService for PingSvc { + type Response = super::PingResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::ping(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = PingSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for CompactTxStreamerServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService + for CompactTxStreamerServer { + const NAME: &'static str = "cash.z.wallet.sdk.rpc.CompactTxStreamer"; + } +} diff --git a/zingo-rpc/src/queue.rs b/zingo-rpc/src/queue.rs index 0ebea07..6c82246 100644 --- a/zingo-rpc/src/queue.rs +++ b/zingo-rpc/src/queue.rs @@ -1,3 +1,4 @@ //! Zingo-Proxy request queue. +pub mod error; pub mod request; diff --git a/zingo-rpc/src/queue/error.rs b/zingo-rpc/src/queue/error.rs new file mode 100644 index 0000000..697eb62 --- /dev/null +++ b/zingo-rpc/src/queue/error.rs @@ -0,0 +1,17 @@ +//! Hold error types for the queue and related functionality. + +use crate::nym::error::NymError; + +/// Zingo-Proxy request errors. +#[derive(Debug, thiserror::Error)] +pub enum RequestError { + /// Errors originating from incorrect enum types being called. + #[error("Incorrect variant")] + IncorrectVariant, + /// System time errors. + #[error("System time error: {0}")] + SystemTimeError(#[from] std::time::SystemTimeError), + /// Nym Related Errors + #[error("Nym error: {0}")] + NymError(#[from] NymError), +} diff --git a/zingo-rpc/src/queue/request.rs b/zingo-rpc/src/queue/request.rs index e510f11..9a3a8e6 100644 --- a/zingo-rpc/src/queue/request.rs +++ b/zingo-rpc/src/queue/request.rs @@ -5,18 +5,7 @@ use std::time::SystemTime; use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag; use tonic::metadata::MetadataMap; -use crate::nym::utils::read_nym_request_data; - -/// Zingo-Proxy request errors. -#[derive(Debug, thiserror::Error)] -pub enum RequestError { - /// Errors originating from incorrect enum types being called. - #[error("Incorrect variant")] - IncorrectVariant, - /// System time errors. - #[error("System time error: {0}")] - SystemTimeError(#[from] std::time::SystemTimeError), -} +use crate::{nym::utils::read_nym_request_data, queue::error::RequestError}; /// Requests queuing metadata. #[derive(Debug)] @@ -129,9 +118,9 @@ pub enum ZingoProxyRequest { impl ZingoProxyRequest { /// Creates a ZingoProxyRequest from an encoded gRPC service call, recieved by the Nym server. - pub fn new_from_nym(metadata: AnonymousSenderTag, bytes: &[u8]) -> Self { - let (id, method, body) = read_nym_request_data(bytes).unwrap(); - ZingoProxyRequest::NymServerRequest(NymServerRequest { + pub fn new_from_nym(metadata: AnonymousSenderTag, bytes: &[u8]) -> Result { + let (id, method, body) = read_nym_request_data(bytes)?; + Ok(ZingoProxyRequest::NymServerRequest(NymServerRequest { queuedata: QueueData::new(), request: NymRequest { id, @@ -139,7 +128,7 @@ impl ZingoProxyRequest { metadata: RequestMetaData::AnonSendrTag(metadata), body: body.to_vec(), }, - }) + })) } /// Creates a ZingoProxyRequest from a gRPC service call, recieved by the gRPC server. diff --git a/zingo-rpc/src/rpc/nymservice.rs b/zingo-rpc/src/rpc/nymservice.rs index fd8cde0..b9b3f17 100644 --- a/zingo-rpc/src/rpc/nymservice.rs +++ b/zingo-rpc/src/rpc/nymservice.rs @@ -1,9 +1,14 @@ //! Lightwallet service RPC Nym implementations. use prost::Message; -use zcash_client_backend::proto::service::compact_tx_streamer_server::CompactTxStreamer; -use crate::{primitives::ProxyClient, queue::request::ZingoProxyRequest}; +use crate::{primitives::client::ProxyClient, queue::request::ZingoProxyRequest}; + +#[cfg(not(feature = "nym_poc"))] +use crate::proto::service::compact_tx_streamer_server::CompactTxStreamer; + +#[cfg(feature = "nym_poc")] +use zcash_client_backend::proto::service::compact_tx_streamer_server::CompactTxStreamer; impl ProxyClient { /// Processes gRPC requests coming from the nym server. diff --git a/zingo-rpc/src/rpc/nymwalletservice.rs b/zingo-rpc/src/rpc/nymwalletservice.rs index 23595fe..c1c7c97 100644 --- a/zingo-rpc/src/rpc/nymwalletservice.rs +++ b/zingo-rpc/src/rpc/nymwalletservice.rs @@ -4,21 +4,54 @@ use std::env; use tonic::{async_trait, Request, Response, Status}; + +use crate::{ + primitives::client::{NymClient, ProxyClient}, + walletrpc::utils::{deserialize_response, serialize_request, write_nym_request_data}, +}; use zcash_client_backend::proto::{ compact_formats::{CompactBlock, CompactTx}, service::{ compact_tx_streamer_server::CompactTxStreamer, Address, AddressList, Balance, BlockId, - BlockRange, ChainSpec, Empty, Exclude, GetAddressUtxosArg, GetAddressUtxosReply, + BlockRange, ChainSpec, Duration, Empty, Exclude, GetAddressUtxosArg, GetAddressUtxosReply, GetAddressUtxosReplyList, GetSubtreeRootsArg, LightdInfo, PingResponse, RawTransaction, SendResponse, SubtreeRoot, TransparentAddressBlockFilter, TreeState, TxFilter, }, }; -use crate::{ - define_grpc_passthrough, - primitives::{NymClient, ProxyClient}, - walletrpc::utils::{deserialize_response, serialize_request, write_nym_request_data}, -}; +macro_rules! define_grpc_passthrough { + (fn + $name:ident( + &$self:ident$(,$($arg:ident: $argty:ty,)*)? + ) -> $ret:ty + ) => { + #[must_use] + #[allow(clippy::type_complexity, clippy::type_repetition_in_bounds)] + fn $name<'life0, 'async_trait>(&'life0 $self$($(, $arg: $argty)*)?) -> + ::core::pin::Pin, + ::tonic::Status + > + > + ::core::marker::Send + 'async_trait + >> + where + 'life0: 'async_trait, + Self: 'async_trait, + { + println!("@zingoproxyd: Received call of {}.", stringify!($name)); + Box::pin(async { + ::zingo_netutils::GrpcConnector::new($self.lightwalletd_uri.clone()) + .get_client() + .await + .expect("Proxy server failed to create client") + .$name($($($arg),*)?) + .await + }) + } + }; +} #[async_trait] impl CompactTxStreamer for ProxyClient { @@ -86,11 +119,10 @@ impl CompactTxStreamer for ProxyClient { let args: Vec = env::args().collect(); let recipient_address: String = args[1].clone(); let nym_conf_path = "/tmp/nym_client"; - let mut client = NymClient::nym_spawn(nym_conf_path).await; + let mut client = NymClient::nym_spawn(nym_conf_path).await?; let response_data = client .nym_forward(recipient_address.as_str(), nym_request) - .await - .unwrap(); + .await?; client.nym_close().await; // -- deserialize SendResponse let response: SendResponse = match deserialize_response(response_data.as_slice()).await { @@ -225,11 +257,10 @@ impl CompactTxStreamer for ProxyClient { let args: Vec = env::args().collect(); let recipient_address: String = args[1].clone(); let nym_conf_path = "/tmp/nym_client"; - let mut client = NymClient::nym_spawn(nym_conf_path).await; + let mut client = NymClient::nym_spawn(nym_conf_path).await?; let response_data = client .nym_forward(recipient_address.as_str(), nym_request) - .await - .unwrap(); + .await?; client.nym_close().await; // -- deserialize LightdInfo let response: LightdInfo = match deserialize_response(response_data.as_slice()).await { @@ -247,7 +278,7 @@ impl CompactTxStreamer for ProxyClient { define_grpc_passthrough!( fn ping( &self, - request: tonic::Request, + request: tonic::Request, ) -> PingResponse ); diff --git a/zingo-rpc/src/rpc/service.rs b/zingo-rpc/src/rpc/service.rs index ae99841..aa85627 100644 --- a/zingo-rpc/src/rpc/service.rs +++ b/zingo-rpc/src/rpc/service.rs @@ -3,22 +3,25 @@ use hex::FromHex; use tokio::time::timeout; use tokio_stream::wrappers::ReceiverStream; -use zcash_client_backend::proto::{ - compact_formats::{CompactBlock, CompactTx}, - service::{ - compact_tx_streamer_server::CompactTxStreamer, Address, Balance, BlockId, Empty, - GetAddressUtxosReply, LightdInfo, RawTransaction, SubtreeRoot, - }, -}; -use zebra_chain::block::Height; use crate::{ blockcache::{block::get_block_from_node, mempool::Mempool}, - jsonrpc::{ - connector::JsonRpcConnector, - primitives::{GetTransactionResponse, ProxyConsensusBranchIdHex}, + jsonrpc::{connector::JsonRpcConnector, primitives::GetTransactionResponse}, + primitives::{ + chain::{ConsensusBranchId, ConsensusBranchIdHex}, + client::ProxyClient, + height::ChainHeight, + }, + proto::{ + compact_formats::{CompactBlock, CompactTx}, + service::{ + compact_tx_streamer_server::CompactTxStreamer, Address, AddressList, Balance, BlockId, + BlockRange, ChainSpec, Duration, Empty, Exclude, GetAddressUtxosArg, + GetAddressUtxosReply, GetAddressUtxosReplyList, GetSubtreeRootsArg, LightdInfo, + PingResponse, RawTransaction, SendResponse, SubtreeRoot, TransparentAddressBlockFilter, + TreeState, TxFilter, + }, }, - primitives::ProxyClient, utils::get_build_info, }; @@ -88,14 +91,11 @@ impl CompactTxStreamer for ProxyClient { /// Return the height of the tip of the best chain. fn get_latest_block<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -133,14 +133,11 @@ impl CompactTxStreamer for ProxyClient { /// TODO: This RPC should be implemented alongside the block cache. fn get_block<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -161,14 +158,11 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_block_nullifiers<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -193,7 +187,7 @@ impl CompactTxStreamer for ProxyClient { /// - add get_block function that queries the block cache for block and calls get_block_from_node to fetch block if not present. fn get_block_range<'life0, 'async_trait>( &'life0 self, - request: tonic::Request, + request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -224,10 +218,16 @@ impl CompactTxStreamer for ProxyClient { if start > end { (start, end) = (end, start); } + println!( + "@zingoproxytest: Fetching blocks in range: {}-{}.", + start, end + ); let (channel_tx, channel_rx) = tokio::sync::mpsc::channel(32); tokio::spawn(async move { - let timeout = timeout(std::time::Duration::from_secs(30), async { + // NOTE: This timeout is so slow due to the blockcache not being implemented. This should be reduced to 30s once functionality is in place. + let timeout = timeout(std::time::Duration::from_secs(120), async { for height in (start..=end).rev() { + println!("@zingoproxytest: Fetching block at height: {}.", height); let compact_block = get_block_from_node(&zebrad_uri, &height).await; match compact_block { Ok(block) => { @@ -252,7 +252,9 @@ impl CompactTxStreamer for ProxyClient { Ok(_) => {} Err(_) => { channel_tx - .send(Err(tonic::Status::internal("Request timed out"))) + .send(Err(tonic::Status::internal( + "get_block_range gRPC request timed out", + ))) .await .ok(); } @@ -274,7 +276,7 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_block_range_nullifiers<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -299,14 +301,11 @@ impl CompactTxStreamer for ProxyClient { /// Return the requested full (not compact) transaction (as from zcashd). fn get_transaction<'life0, 'async_trait>( &'life0 self, - request: tonic::Request, + request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -342,12 +341,10 @@ impl CompactTxStreamer for ProxyClient { ) })?; - Ok(tonic::Response::new( - zcash_client_backend::proto::service::RawTransaction { - data: hex.bytes, - height, - }, - )) + Ok(tonic::Response::new(RawTransaction { + data: hex.bytes, + height, + })) } else { Err(tonic::Status::invalid_argument( "Transaction hash incorrect", @@ -359,14 +356,11 @@ impl CompactTxStreamer for ProxyClient { /// Submit the given transaction to the Zcash network. fn send_transaction<'life0, 'async_trait>( &'life0 self, - request: tonic::Request, + request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -388,12 +382,10 @@ impl CompactTxStreamer for ProxyClient { .await .map_err(|e| e.to_grpc_status())?; - Ok(tonic::Response::new( - zcash_client_backend::proto::service::SendResponse { - error_code: 0, - error_message: tx_output.0.to_string(), - }, - )) + Ok(tonic::Response::new(SendResponse { + error_code: 0, + error_message: tx_output.0.to_string(), + })) }) } @@ -404,9 +396,7 @@ impl CompactTxStreamer for ProxyClient { /// This name is misleading, returns the full transactions that have either inputs or outputs connected to the given transparent address. fn get_taddress_txids<'life0, 'async_trait>( &'life0 self, - request: tonic::Request< - zcash_client_backend::proto::service::TransparentAddressBlockFilter, - >, + request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -495,7 +485,9 @@ impl CompactTxStreamer for ProxyClient { Ok(_) => {} Err(_) => { channel_tx - .send(Err(tonic::Status::internal("Request timed out"))) + .send(Err(tonic::Status::internal( + "get_taddress_txids gRPC request timed out", + ))) .await .ok(); } @@ -511,14 +503,11 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_taddress_balance<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -575,7 +564,7 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_mempool_tx<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -716,7 +705,9 @@ impl CompactTxStreamer for ProxyClient { Ok(_) => {} Err(_) => { channel_tx - .send(Err(tonic::Status::internal("Request timed out"))) + .send(Err(tonic::Status::internal( + "get_mempool_stream gRPC request timed out", + ))) .await .ok(); } @@ -734,14 +725,11 @@ impl CompactTxStreamer for ProxyClient { /// The block can be specified by either height or hash. fn get_tree_state<'life0, 'async_trait>( &'life0 self, - request: tonic::Request, + request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -776,16 +764,14 @@ impl CompactTxStreamer for ProxyClient { .get_treestate(hash_or_height) .await .map_err(|e| e.to_grpc_status())?; - Ok(tonic::Response::new( - zcash_client_backend::proto::service::TreeState { - network: chain, - height: treestate.height as u64, - hash: treestate.hash.to_string(), - time: treestate.time, - sapling_tree: treestate.sapling.commitments.final_state.to_string(), - orchard_tree: treestate.orchard.commitments.final_state.to_string(), - }, - )) + Ok(tonic::Response::new(TreeState { + network: chain, + height: treestate.height as u64, + hash: treestate.hash.to_string(), + time: treestate.time, + sapling_tree: treestate.sapling.commitments.final_state.to_string(), + orchard_tree: treestate.orchard.commitments.final_state.to_string(), + })) }) } @@ -797,10 +783,7 @@ impl CompactTxStreamer for ProxyClient { ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -826,7 +809,7 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_subtree_roots<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -852,14 +835,12 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_address_utxos<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< Output = std::result::Result< - tonic::Response< - zcash_client_backend::proto::service::GetAddressUtxosReplyList, - >, + tonic::Response, tonic::Status, >, > + core::marker::Send @@ -884,7 +865,7 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn get_address_utxos_stream<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< @@ -913,10 +894,7 @@ impl CompactTxStreamer for ProxyClient { ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, @@ -946,19 +924,19 @@ impl CompactTxStreamer for ProxyClient { .map_err(|e| e.to_grpc_status())?; let sapling_id_str = "76b809bb"; - let sapling_id = ProxyConsensusBranchIdHex( - zebra_chain::parameters::ConsensusBranchId::from_hex(sapling_id_str).map_err( - |_e| { - tonic::Status::internal( - "Internal Error - Consesnsus Branch ID hex conversion failed", - ) - }, - )?, + let sapling_id = ConsensusBranchIdHex( + ConsensusBranchId::from_hex(sapling_id_str).map_err(|_e| { + tonic::Status::internal( + "Internal Error - Consesnsus Branch ID hex conversion failed", + ) + })?, ); let sapling_height = blockchain_info .upgrades .get(&sapling_id) - .map_or(Height(1), |sapling_json| sapling_json.activation_height); + .map_or(ChainHeight(1), |sapling_json| { + sapling_json.activation_height + }); let build_info = get_build_info(); @@ -988,14 +966,11 @@ impl CompactTxStreamer for ProxyClient { /// If you require this RPC please open an issue or PR at the Zingo-Proxy github (https://github.com/zingolabs/zingo-proxy). fn ping<'life0, 'async_trait>( &'life0 self, - _request: tonic::Request, + _request: tonic::Request, ) -> core::pin::Pin< Box< dyn core::future::Future< - Output = std::result::Result< - tonic::Response, - tonic::Status, - >, + Output = std::result::Result, tonic::Status>, > + core::marker::Send + 'async_trait, >, diff --git a/zingo-rpc/src/utils.rs b/zingo-rpc/src/utils.rs index ba077b4..4a50027 100644 --- a/zingo-rpc/src/utils.rs +++ b/zingo-rpc/src/utils.rs @@ -1,41 +1,5 @@ //! Utility functions for Zingo-RPC. -/// Passes unimplemented RPCs on to Lightwalletd. -#[macro_export] -macro_rules! define_grpc_passthrough { - (fn - $name:ident( - &$self:ident$(,$($arg:ident: $argty:ty,)*)? - ) -> $ret:ty - ) => { - #[must_use] - #[allow(clippy::type_complexity, clippy::type_repetition_in_bounds)] - fn $name<'life0, 'async_trait>(&'life0 $self$($(, $arg: $argty)*)?) -> - ::core::pin::Pin, - ::tonic::Status - > - > + ::core::marker::Send + 'async_trait - >> - where - 'life0: 'async_trait, - Self: 'async_trait, - { - println!("@zingoproxyd: Received call of {}.", stringify!($name)); - Box::pin(async { - ::zingo_netutils::GrpcConnector::new($self.lightwalletd_uri.clone()) - .get_client() - .await - .expect("Proxy server failed to create client") - .$name($($($arg),*)?) - .await - }) - } - }; -} - /// Zingo-Proxy build info. pub struct BuildInfo { /// Git commit hash. diff --git a/zingo-rpc/src/walletrpc/service.rs b/zingo-rpc/src/walletrpc/service.rs index 989d86d..d012809 100644 --- a/zingo-rpc/src/walletrpc/service.rs +++ b/zingo-rpc/src/walletrpc/service.rs @@ -2,30 +2,28 @@ //! //! NOTE: Currently only send_transaction has been implemented over nym. +use bytes::Bytes; use http::Uri; use http_body::Body; -use zcash_client_backend::proto::compact_formats::{CompactBlock, CompactTx}; -use zcash_client_backend::proto::service::{ - compact_tx_streamer_client::CompactTxStreamerClient, RawTransaction, SendResponse, -}; -use zcash_client_backend::proto::service::{ - Address, AddressList, Balance, BlockId, BlockRange, ChainSpec, Duration, Empty, Exclude, - GetAddressUtxosArg, GetAddressUtxosReply, GetAddressUtxosReplyList, GetSubtreeRootsArg, - LightdInfo, PingResponse, SubtreeRoot, TransparentAddressBlockFilter, TreeState, TxFilter, -}; - -use bytes::Bytes; use std::error::Error as StdError; use tonic::{self, codec::CompressionEncoding, Status}; use tonic::{service::interceptor::InterceptedService, transport::Endpoint}; use crate::{ - primitives::NymClient, - walletrpc::utils::{deserialize_response, serialize_request}, + primitives::client::NymClient, + proto::{ + compact_formats::{CompactBlock, CompactTx}, + service::{ + compact_tx_streamer_client::CompactTxStreamerClient, Address, AddressList, Balance, + BlockId, BlockRange, ChainSpec, Duration, Empty, Exclude, GetAddressUtxosArg, + GetAddressUtxosReply, GetAddressUtxosReplyList, GetSubtreeRootsArg, LightdInfo, + PingResponse, RawTransaction, SendResponse, SubtreeRoot, TransparentAddressBlockFilter, + TreeState, TxFilter, + }, + }, + walletrpc::utils::{deserialize_response, serialize_request, write_nym_request_data}, }; -use super::utils::write_nym_request_data; - /// Wrapper struct for the Nym enabled CompactTxStreamerClient. #[derive(Debug, Clone)] pub struct NymTxStreamerClient { @@ -240,8 +238,8 @@ where } }; let nym_conf_path = "/tmp/nym_client"; - let mut client = NymClient::nym_spawn(nym_conf_path).await; - let response_data = client.nym_forward(addr, nym_request).await.unwrap(); + let mut client = NymClient::nym_spawn(nym_conf_path).await?; + let response_data = client.nym_forward(addr, nym_request).await?; client.nym_close().await; let response: SendResponse = match deserialize_response(response_data.as_slice()).await { @@ -428,8 +426,8 @@ where } }; let nym_conf_path = "/tmp/nym_client"; - let mut client = NymClient::nym_spawn(nym_conf_path).await; - let response_data = client.nym_forward(addr, nym_request).await.unwrap(); + let mut client = NymClient::nym_spawn(nym_conf_path).await?; + let response_data = client.nym_forward(addr, nym_request).await?; client.nym_close().await; let response: LightdInfo = match deserialize_response(response_data.as_slice()).await { diff --git a/zingo-rpc/src/walletrpc/utils.rs b/zingo-rpc/src/walletrpc/utils.rs index f08c609..a513d8d 100644 --- a/zingo-rpc/src/walletrpc/utils.rs +++ b/zingo-rpc/src/walletrpc/utils.rs @@ -1,8 +1,9 @@ //! Utility functions for wallet side nym code. -use zcash_encoding::CompactSize; - -use crate::blockcache::utils::ParseError; +use crate::{ + blockcache::{error::ParseError, utils::CompactSize}, + nym::error::NymError, +}; /// Serialises gRPC request to a buffer. pub async fn serialize_request( @@ -14,23 +15,21 @@ pub async fn serialize_request( } /// Decodes gRPC request from a buffer -pub async fn deserialize_response( - data: &[u8], -) -> Result { - T::decode(data).map_err(ParseError::from) +pub async fn deserialize_response(data: &[u8]) -> Result { + T::decode(data).map_err(|e| NymError::from(ParseError::from(e))) } /// Prepends an encoded tonic request with metadata required by the Nym server. /// /// Encodes the request ID as a Zcash CompactSize [u64]. /// Encodes the RPC method String into a Vec prepended by a Zcash CompactSize indicating its length in bytes. -pub fn write_nym_request_data(id: u64, method: String, body: &[u8]) -> Result, ParseError> { +pub fn write_nym_request_data(id: u64, method: String, body: &[u8]) -> Result, NymError> { let method_bytes = method.into_bytes(); let mut buffer = Vec::new(); - CompactSize::write(&mut buffer, id as usize)?; - CompactSize::write(&mut buffer, method_bytes.len())?; + CompactSize::write(&mut buffer, id as usize).map_err(ParseError::Io)?; + CompactSize::write(&mut buffer, method_bytes.len()).map_err(ParseError::Io)?; buffer.extend(method_bytes); - CompactSize::write(&mut buffer, body.len())?; + CompactSize::write(&mut buffer, body.len()).map_err(ParseError::Io)?; buffer.extend(body); Ok(buffer) } diff --git a/zingoproxy-testutils/Cargo.toml b/zingoproxy-testutils/Cargo.toml index 01e0038..65daed5 100644 --- a/zingoproxy-testutils/Cargo.toml +++ b/zingoproxy-testutils/Cargo.toml @@ -1,11 +1,13 @@ [package] name = "zingoproxy-testutils" version = "0.1.0" -authors = ["zingo@zingolabs.org"] -edition = "2021" +description = "Crate containing Zingo-Proxy test specific functionality." +edition = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +repository = { workspace = true } [features] -nym = [] # NOTE: Deprecated nym_poc = [] @@ -13,22 +15,20 @@ nym_poc = [] zingo-rpc = { path = "../zingo-rpc" } zingo-proxyd = { path = "../zingo-proxyd" } -zcash_client_backend = { workspace = true } - -nym-sdk = { workspace = true } - -tokio = { workspace = true } -http = { workspace = true } -tonic = { workspace = true } - +# ZingoLib zingo-testutils = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration" } zingoconfig = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration" } zingolib = { git = "https://github.com/zingolabs/zingolib.git", branch = "nym_integration" } -# zingo-testutils = { path = "../../zingolib/zingo-testutils" } -# zingoconfig = { path = "../../zingolib/zingoconfig" } -# zingolib = { path = "../../zingolib/zingolib" } +# zingo-testutils = { git = "https://github.com/zingolabs/zingolib.git", tag = "mob-release-1.4.2", package = "zingo-testutils" } +# zingoconfig = { git = "https://github.com/zingolabs/zingolib.git", tag = "mob-release-1.4.2", package = "zingoconfig" } +# zingolib = { git = "https://github.com/zingolabs/zingolib.git", tag = "mob-release-1.4.2", package = "zingolib" } + +# Miscellaneous Workspace +tokio = { workspace = true } +tonic = { workspace = true } +http = { workspace = true } -ctrlc = "3.2.1" -tempfile = "3.2.0" -chrono = "0.4.19" +# Miscellaneous Crate +ctrlc = "3.2.1" # "3.4.4" +tempfile = "3.2.0" # "3.10.1" portpicker = "0.1.1" diff --git a/zingoproxy-testutils/src/lib.rs b/zingoproxy-testutils/src/lib.rs index 41767a9..0190a14 100644 --- a/zingoproxy-testutils/src/lib.rs +++ b/zingoproxy-testutils/src/lib.rs @@ -180,6 +180,8 @@ fn set_custom_drops( ); } } + // Assures tests fail on secondary thread panics. + assert!(false); std::process::exit(0); })); @@ -203,6 +205,8 @@ fn set_custom_drops( ); } } + // Assures tests fail on ctrlc exit. + assert!(false); std::process::exit(0); }) .expect("Error setting Ctrl-C handler"); @@ -261,3 +265,58 @@ fn create_temp_conf_files( write_zcash_conf(&conf_dir, rpcport)?; Ok(temp_dir) } + +/// Returns the zcash address of the Zingolib::lightclient. +pub async fn get_zingo_address( + zingo_client: &zingolib::lightclient::LightClient, + pool: &str, +) -> String { + zingolib::get_base_address!(zingo_client, pool) +} + +/// Starts Zingolib::lightclients's mempool monitor. +pub async fn start_zingo_mempool_monitor(zingo_client: &zingolib::lightclient::LightClient) { + let zingo_client_saved = zingo_client.export_save_buffer_async().await.unwrap(); + let zingo_client_loaded = std::sync::Arc::new( + zingolib::lightclient::LightClient::read_wallet_from_buffer_async( + zingo_client.config(), + &zingo_client_saved[..], + ) + .await + .unwrap(), + ); + zingolib::lightclient::LightClient::start_mempool_monitor(zingo_client_loaded.clone()); + // This seems to be long enough for the mempool monitor to kick in (from zingolib). + tokio::time::sleep(std::time::Duration::from_secs(5)).await; +} + +/// Zingo-Proxy wrapper for Zingolib's Pool Enum. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ProxyPool { + /// Orchard pool. + Orchard, + /// Sapling pool + Sapling, + /// Transparent poool. + Transparent, +} + +impl From for zingolib::wallet::Pool { + fn from(test_pool: ProxyPool) -> Self { + match test_pool { + ProxyPool::Orchard => zingolib::wallet::Pool::Orchard, + ProxyPool::Sapling => zingolib::wallet::Pool::Sapling, + ProxyPool::Transparent => zingolib::wallet::Pool::Transparent, + } + } +} + +impl From for ProxyPool { + fn from(pool: zingolib::wallet::Pool) -> Self { + match pool { + zingolib::wallet::Pool::Orchard => ProxyPool::Orchard, + zingolib::wallet::Pool::Sapling => ProxyPool::Sapling, + zingolib::wallet::Pool::Transparent => ProxyPool::Transparent, + } + } +}