diff --git a/Cargo.lock b/Cargo.lock index 625a3c5c21..e5ec26bc64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "aead" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" +dependencies = [ + "crypto-common", + "generic-array", +] + [[package]] name = "aes" version = "0.7.5" @@ -18,7 +28,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if", - "cipher", + "cipher 0.3.0", "cpufeatures", "opaque-debug", ] @@ -324,7 +334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" dependencies = [ "block-padding", - "cipher", + "cipher 0.3.0", ] [[package]] @@ -402,21 +412,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ "cfg-if", - "cipher", + "cipher 0.3.0", "cpufeatures", "zeroize", ] +[[package]] +name = "chacha20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08" +dependencies = [ + "cfg-if", + "cipher 0.4.3", + "cpufeatures", +] + [[package]] name = "chacha20poly1305" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", + "aead 0.4.3", + "chacha20 0.8.2", + "cipher 0.3.0", + "poly1305 0.7.2", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead 0.5.1", + "chacha20 0.9.0", + "cipher 0.4.3", + "poly1305 0.8.0", "zeroize", ] @@ -444,6 +478,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clap" version = "3.2.23" @@ -616,9 +661,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" dependencies = [ "cc", "cxxbridge-flags", @@ -628,9 +673,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" dependencies = [ "cc", "codespan-reporting", @@ -643,15 +688,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" [[package]] name = "cxxbridge-macro" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ "proc-macro2", "quote", @@ -686,9 +731,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -781,6 +826,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "equihash" +version = "0.2.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "blake2b_simd", + "byteorder", +] + [[package]] name = "equihash" version = "0.2.0" @@ -821,6 +875,14 @@ dependencies = [ "str-buf", ] +[[package]] +name = "f4jumble" +version = "0.1.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "blake2b_simd", +] + [[package]] name = "f4jumble" version = "0.1.0" @@ -903,7 +965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd910db5f9ca4dc3116f8c46367825807aa2b942f72565f16b4be0b208a00a9e" dependencies = [ "block-modes", - "cipher", + "cipher 0.3.0", "libm", "num-bigint", "num-integer", @@ -1039,6 +1101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", + "memuse", "rand_core 0.6.4", "subtle", ] @@ -1156,7 +1219,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -1314,14 +1377,23 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -1729,7 +1801,37 @@ dependencies = [ [[package]] name = "orchard" version = "0.2.0" -source = "git+https://github.com/zingolabs/orchard?rev=49874b31da4fedcb31fcfadf5ba8804bf860c4bf#49874b31da4fedcb31fcfadf5ba8804bf860c4bf" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7619db7f917afd9b1139044c595fab1b6166de2db62317794b5f5e34a2104ae1" +dependencies = [ + "aes", + "bitvec", + "blake2b_simd", + "ff", + "fpe", + "group", + "halo2_gadgets", + "halo2_proofs", + "hex 0.4.3", + "incrementalmerkletree", + "lazy_static", + "memuse", + "nonempty", + "pasta_curves", + "proptest", + "rand 0.8.5", + "reddsa", + "serde", + "subtle", + "tracing", + "zcash_note_encryption 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orchard" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f06b263206a75a7d96ca75d46a3e9ca8eaf7ab7feea209749bb8b818d22f427" dependencies = [ "aes", "bitvec", @@ -1751,7 +1853,7 @@ dependencies = [ "serde", "subtle", "tracing", - "zcash_note_encryption", + "zcash_note_encryption 0.2.0", ] [[package]] @@ -1849,7 +1951,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "password-hash", ] @@ -1915,7 +2017,18 @@ checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" dependencies = [ "cpufeatures", "opaque-debug", - "universal-hash", + "universal-hash 0.4.1", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash 0.5.0", ] [[package]] @@ -1985,7 +2098,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes 1.2.1", - "prost-derive", + "prost-derive 0.10.1", +] + +[[package]] +name = "prost" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" +dependencies = [ + "bytes 1.2.1", + "prost-derive 0.11.2", ] [[package]] @@ -2003,13 +2126,35 @@ dependencies = [ "log", "multimap", "petgraph", - "prost", - "prost-types", + "prost 0.10.4", + "prost-types 0.10.1", "regex", "tempfile", "which", ] +[[package]] +name = "prost-build" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511" +dependencies = [ + "bytes 1.2.1", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost 0.11.2", + "prost-types 0.11.2", + "regex", + "syn", + "tempfile", + "which", +] + [[package]] name = "prost-derive" version = "0.10.1" @@ -2023,6 +2168,19 @@ dependencies = [ "syn", ] +[[package]] +name = "prost-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "prost-types" version = "0.10.1" @@ -2030,7 +2188,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes 1.2.1", - "prost", + "prost 0.10.4", +] + +[[package]] +name = "prost-types" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +dependencies = [ + "bytes 1.2.1", + "prost 0.11.2", ] [[package]] @@ -2164,11 +2332,10 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ - "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -2176,9 +2343,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "7ebf1bc4b691de61bd5a8ba170bfd6a1d363ff3cb595a51798d107aab25d2466" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -2332,7 +2499,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -2391,9 +2558,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812a2ec2043c4d6bc6482f5be2ab8244613cac2493d128d36c0759e52a626ab3" +checksum = "203974af07ea769452490ee8de3e5947971efc3a090dca8a779dd432d3fa46a7" dependencies = [ "bitflags", "errno", @@ -2537,6 +2704,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.7.0" @@ -2607,9 +2783,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7" dependencies = [ "itoa", "ryu", @@ -2676,7 +2852,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3018,9 +3194,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.21.2" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ "autocfg", "bytes 1.2.1", @@ -3123,8 +3299,8 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost", - "prost-derive", + "prost 0.10.4", + "prost-derive 0.10.1", "rustls-native-certs", "rustls-pemfile", "tokio", @@ -3147,7 +3323,20 @@ checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" dependencies = [ "prettyplease", "proc-macro2", - "prost-build", + "prost-build 0.10.4", + "quote", + "syn", +] + +[[package]] +name = "tonic-build" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c6fd7c2581e36d63388a9e04c350c21beb7a8b059580b2e93993c526899ddc" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.11.2", "quote", "syn", ] @@ -3372,6 +3561,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unsafe-any-ors" version = "1.0.0" @@ -3754,8 +3953,19 @@ source = "git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c240 dependencies = [ "bech32 0.8.1", "bs58", - "f4jumble", - "zcash_encoding", + "f4jumble 0.1.0 (git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346)", + "zcash_encoding 0.1.0", +] + +[[package]] +name = "zcash_address" +version = "0.2.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "bech32 0.8.1", + "bs58", + "f4jumble 0.1.0 (git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990)", + "zcash_encoding 0.2.0", ] [[package]] @@ -3774,7 +3984,7 @@ dependencies = [ "jubjub", "log", "nom", - "orchard", + "orchard 0.2.0", "percent-encoding", "protobuf", "protobuf-codegen-pure", @@ -3783,9 +3993,38 @@ dependencies = [ "subtle", "time 0.2.27", "tracing", - "zcash_address", - "zcash_note_encryption", - "zcash_primitives", + "zcash_address 0.1.0", + "zcash_note_encryption 0.1.0 (git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346)", + "zcash_primitives 0.7.0", +] + +[[package]] +name = "zcash_client_backend" +version = "0.6.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "base64", + "bech32 0.8.1", + "bls12_381", + "bs58", + "crossbeam-channel", + "group", + "memuse", + "nom", + "orchard 0.3.0", + "percent-encoding", + "prost 0.11.2", + "rayon", + "secrecy", + "subtle", + "time 0.2.27", + "tonic-build 0.8.2", + "tracing", + "which", + "zcash_address 0.2.0", + "zcash_encoding 0.2.0", + "zcash_note_encryption 0.2.0", + "zcash_primitives 0.9.0", ] [[package]] @@ -3797,13 +4036,46 @@ dependencies = [ "nonempty", ] +[[package]] +name = "zcash_encoding" +version = "0.2.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "byteorder", + "nonempty", +] + +[[package]] +name = "zcash_note_encryption" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f84ae538f05a8ac74c82527f06b77045ed9553a0871d9db036166a4c344e3a" +dependencies = [ + "chacha20 0.8.2", + "chacha20poly1305 0.9.1", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "zcash_note_encryption" version = "0.1.0" source = "git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346#d66f7f70516e6da5c24008874a926d41221b1346" dependencies = [ - "chacha20", - "chacha20poly1305", + "chacha20 0.8.2", + "chacha20poly1305 0.9.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "zcash_note_encryption" +version = "0.2.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "chacha20 0.9.0", + "chacha20poly1305 0.10.1", + "cipher 0.4.3", "rand_core 0.6.4", "subtle", ] @@ -3821,8 +4093,44 @@ dependencies = [ "bls12_381", "bs58", "byteorder", - "chacha20poly1305", - "equihash", + "chacha20poly1305 0.9.1", + "equihash 0.2.0 (git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346)", + "ff", + "fpe", + "group", + "hdwallet", + "hex 0.4.3", + "incrementalmerkletree", + "jubjub", + "lazy_static", + "memuse", + "nonempty", + "orchard 0.2.0", + "proptest", + "rand 0.8.5", + "rand_core 0.6.4", + "ripemd", + "secp256k1", + "sha2 0.9.9", + "subtle", + "zcash_address 0.1.0", + "zcash_encoding 0.1.0", + "zcash_note_encryption 0.1.0 (git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346)", +] + +[[package]] +name = "zcash_primitives" +version = "0.9.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "aes", + "bip0039 0.9.0", + "bitvec", + "blake2b_simd", + "blake2s_simd", + "bls12_381", + "byteorder", + "equihash 0.2.0 (git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990)", "ff", "fpe", "group", @@ -3833,7 +4141,7 @@ dependencies = [ "lazy_static", "memuse", "nonempty", - "orchard", + "orchard 0.3.0", "proptest", "rand 0.8.5", "rand_core 0.6.4", @@ -3841,9 +4149,9 @@ dependencies = [ "secp256k1", "sha2 0.9.9", "subtle", - "zcash_address", - "zcash_encoding", - "zcash_note_encryption", + "zcash_address 0.2.0", + "zcash_encoding 0.2.0", + "zcash_note_encryption 0.2.0", ] [[package]] @@ -3863,7 +4171,25 @@ dependencies = [ "rand_core 0.6.4", "redjubjub", "tracing", - "zcash_primitives", + "zcash_primitives 0.7.0", +] + +[[package]] +name = "zcash_proofs" +version = "0.9.0" +source = "git+https://github.com/zingolabs/librustzcash?rev=01e6bf65542d3ad8190c798a01436d9edcd9f990#01e6bf65542d3ad8190c798a01436d9edcd9f990" +dependencies = [ + "bellman", + "blake2b_simd", + "bls12_381", + "directories", + "group", + "jubjub", + "lazy_static", + "rand_core 0.6.4", + "redjubjub", + "tracing", + "zcash_primitives 0.9.0", ] [[package]] @@ -3903,8 +4229,8 @@ dependencies = [ "tempdir", "tokio", "tracing-subscriber", - "zcash_client_backend", - "zcash_primitives", + "zcash_client_backend 0.6.0", + "zcash_primitives 0.9.0", "zingoconfig 0.1.0", "zingolib 0.2.0", "zingolib 0.2.0 (git+https://github.com/zingolabs/zingolib?rev=f8fb624237fd4923512cc065620b55230676ab82)", @@ -3918,8 +4244,8 @@ dependencies = [ "http", "log", "log4rs", - "zcash_address", - "zcash_primitives", + "zcash_address 0.2.0", + "zcash_primitives 0.9.0", ] [[package]] @@ -3931,8 +4257,8 @@ dependencies = [ "http", "log", "log4rs", - "zcash_address", - "zcash_primitives", + "zcash_address 0.1.0", + "zcash_primitives 0.7.0", ] [[package]] @@ -3962,10 +4288,10 @@ dependencies = [ "log", "log4rs", "nonempty", - "orchard", + "orchard 0.3.0", "pairing", "portpicker", - "prost", + "prost 0.10.4", "rand 0.8.5", "reqwest", "ring", @@ -3982,18 +4308,18 @@ dependencies = [ "tokio-rustls", "tokio-stream", "tonic", - "tonic-build", + "tonic-build 0.7.2", "tower", "tower-http 0.2.5", "tracing", "tracing-subscriber", "webpki-roots 0.21.1", - "zcash_address", - "zcash_client_backend", - "zcash_encoding", - "zcash_note_encryption", - "zcash_primitives", - "zcash_proofs", + "zcash_address 0.2.0", + "zcash_client_backend 0.6.0", + "zcash_encoding 0.2.0", + "zcash_note_encryption 0.2.0", + "zcash_primitives 0.9.0", + "zcash_proofs 0.9.0", "zingoconfig 0.1.0", ] @@ -4024,9 +4350,9 @@ dependencies = [ "log", "log4rs", "nonempty", - "orchard", + "orchard 0.2.0", "pairing", - "prost", + "prost 0.10.4", "rand 0.8.5", "reqwest", "ring", @@ -4042,17 +4368,17 @@ dependencies = [ "tokio-rustls", "tokio-stream", "tonic", - "tonic-build", + "tonic-build 0.7.2", "tower", "tower-http 0.2.5", "tracing", "tracing-subscriber", "webpki-roots 0.21.1", - "zcash_address", - "zcash_client_backend", - "zcash_encoding", - "zcash_note_encryption", - "zcash_primitives", - "zcash_proofs", + "zcash_address 0.1.0", + "zcash_client_backend 0.5.0", + "zcash_encoding 0.1.0", + "zcash_note_encryption 0.1.0 (git+https://github.com/zingolabs/librustzcash?rev=d66f7f70516e6da5c24008874a926d41221b1346)", + "zcash_primitives 0.7.0", + "zcash_proofs 0.7.1", "zingoconfig 0.1.0 (git+https://github.com/zingolabs/zingolib?rev=f8fb624237fd4923512cc065620b55230676ab82)", ] diff --git a/Cargo.toml b/Cargo.toml index f1979418f4..28dfa627cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,5 @@ members = [ debug = false [patch.crates-io] -zcash_note_encryption = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346" } -zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346" } -orchard = { git = "https://github.com/zingolabs/orchard", rev = "49874b31da4fedcb31fcfadf5ba8804bf860c4bf" } \ No newline at end of file +zcash_note_encryption = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990" } +zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990" } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 3436bbd12d..ce5bd9b1e8 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -22,8 +22,8 @@ portpicker = "0.1.1" rand = "0.8.5" tempdir = "0.3.7" tracing-subscriber = "0.3.15" -zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346"} -zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346", features = ["transparent-inputs", "test-dependencies"] } +zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990"} +zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990", features = ["transparent-inputs", "test-dependencies"] } [features] cross_version = [ "dep:zingtaddrfix" ] diff --git a/config/Cargo.toml b/config/Cargo.toml index 1d0d296e10..e4d0143285 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -10,5 +10,5 @@ log4rs = "1.1.1" log = "0.4.14" http = "0.2.4" dirs = "3.0.2" -zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346", features = ["transparent-inputs", "test-dependencies"] } -zcash_address = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346"} +zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990", features = ["transparent-inputs", "test-dependencies"] } +zcash_address = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990"} diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 5be4cb5b3d..be3499f8c1 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -50,15 +50,15 @@ jubjub = "0.9.0" bls12_381 = "0.7" group = "0.12" rust-embed = { version = "6.3.0", features = ["debug-embed"] } -orchard = "0.2.0" +orchard = "0.3.0" subtle = "2.4.1" incrementalmerkletree = "0.3.0" -zcash_address = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346"} -zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346", features = ["transparent-inputs", "test-dependencies"] } -zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346"} -zcash_proofs = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346", features = ["multicore"]} -zcash_encoding = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346"} -zcash_note_encryption = { git = "https://github.com/zingolabs/librustzcash", rev = "d66f7f70516e6da5c24008874a926d41221b1346", features = ["pre-zip-212"]} +zcash_address = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990"} +zcash_primitives = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990", features = ["transparent-inputs", "test-dependencies"] } +zcash_client_backend = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990"} +zcash_proofs = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990", features = ["multicore"]} +zcash_encoding = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990"} +zcash_note_encryption = { git = "https://github.com/zingolabs/librustzcash", rev = "01e6bf65542d3ad8190c798a01436d9edcd9f990", features = ["pre-zip-212"]} zingoconfig = { path = "../config" } nonempty = "0.7.0" tracing-subscriber = "0.3.15" diff --git a/lib/src/blaze/fetch_full_transaction.rs b/lib/src/blaze/fetch_full_transaction.rs index 65c3c92b6d..cbc10429e4 100644 --- a/lib/src/blaze/fetch_full_transaction.rs +++ b/lib/src/blaze/fetch_full_transaction.rs @@ -122,7 +122,7 @@ impl TransactionContext { if is_outgoing_transaction { if let Some(t_bundle) = transaction.transparent_bundle() { for vout in &t_bundle.vout { - let taddr = address_from_pubkeyhash(&self.config, vout.script_pubkey.address()); + let taddr = address_from_pubkeyhash(&self.config, vout.recipient_address()); if taddr.is_some() && !taddrs_set.contains(taddr.as_ref().unwrap()) { outgoing_metadatas.push(OutgoingTxMetadata { @@ -173,7 +173,7 @@ impl TransactionContext { // Scan all transparent outputs to see if we recieved any money if let Some(t_bundle) = transaction.transparent_bundle() { for (n, vout) in t_bundle.vout.iter().enumerate() { - match vout.script_pubkey.address() { + match vout.recipient_address() { Some(TransparentAddress::PublicKey(hash)) => { let output_taddr = hash.to_base58check(&self.config.base58_pubkey_address(), &[]); diff --git a/lib/src/blaze/test_utils.rs b/lib/src/blaze/test_utils.rs index 96c28808ca..6574741149 100644 --- a/lib/src/blaze/test_utils.rs +++ b/lib/src/blaze/test_utils.rs @@ -90,19 +90,6 @@ pub fn node_to_string(n: &Node) -> String { hex::encode(b1) } -///TODO: Is this used? This is probably covered by -/// block_witness_data::update_tree_with_compact_transaction, consider deletion -pub fn list_all_witness_nodes(cb: &CompactBlock) -> Vec { - let mut nodes = vec![]; - for transaction in &cb.vtx { - for co in &transaction.outputs { - nodes.push(sapling::Node::new(co.cmu().unwrap().into())) - } - } - - nodes -} - pub struct FakeTransaction { pub compact_transaction: CompactTx, pub data: TransactionData, @@ -387,7 +374,8 @@ impl FakeCompactBlock { // Returns the nullifier of the new note. pub fn add_random_sapling_transaction(&mut self, num_outputs: usize) { let xsk_m = ExtendedSpendingKey::master(&[1u8; 32]); - let extfvk = ExtendedFullViewingKey::from(&xsk_m); + + let extfvk = xsk_m.to_extended_full_viewing_key(); let to = extfvk.default_address().1; let value = Amount::from_u64(1).unwrap(); @@ -493,7 +481,7 @@ impl FakeCompactBlockList { .iter() .filter_map(|vout| { if let Some(TransparentAddress::PublicKey(taddr_hash)) = - vout.script_pubkey.address() + vout.recipient_address() { let taddr = taddr_hash.to_base58check(&config.base58_pubkey_address(), &[]); diff --git a/lib/src/blaze/trial_decryptions.rs b/lib/src/blaze/trial_decryptions.rs index 663e0931ae..b5df33b0c7 100644 --- a/lib/src/blaze/trial_decryptions.rs +++ b/lib/src/blaze/trial_decryptions.rs @@ -29,7 +29,10 @@ use tokio::{ use zcash_note_encryption::Domain; use zcash_primitives::{ consensus::{BlockHeight, Parameters}, - sapling::{note_encryption::SaplingDomain, SaplingIvk}, + sapling::{ + note_encryption::{PreparedIncomingViewingKey, SaplingDomain}, + SaplingIvk, + }, transaction::{Transaction, TxId}, }; use zingoconfig::ZingoConfig; @@ -185,7 +188,7 @@ impl TrialDecryptions { &compact_transaction, transaction_num, &compact_block, - sapling_ivk.clone(), + PreparedIncomingViewingKey::new(&sapling_ivk), height, &config, &usc, diff --git a/lib/src/lightclient/tests.rs b/lib/src/lightclient/tests.rs index 5331f5213f..c832e129a2 100644 --- a/lib/src/lightclient/tests.rs +++ b/lib/src/lightclient/tests.rs @@ -670,7 +670,7 @@ async fn sapling_to_sapling_scan_together() { let value = 100_000; let (transaction, _height, note) = fake_compactblock_list // NOTE: Extracting fvk this way for future proof. .create_sapling_coinbase_transaction( - &ExtendedFullViewingKey::from(&mockuser_spendkey), + &mockuser_spendkey.to_extended_full_viewing_key(), value, ); let txid = transaction.txid(); diff --git a/lib/src/wallet.rs b/lib/src/wallet.rs index 9fc99d7e12..dddc5197c2 100644 --- a/lib/src/wallet.rs +++ b/lib/src/wallet.rs @@ -15,6 +15,7 @@ use orchard::tree::MerkleHashOrchard; use orchard::Anchor; use rand::rngs::OsRng; use rand::Rng; +use std::cmp::max; use std::{ cmp, collections::HashMap, @@ -31,6 +32,10 @@ use zcash_primitives::merkle_tree::CommitmentTree; use zcash_primitives::sapling::note_encryption::SaplingDomain; use zcash_primitives::sapling::SaplingIvk; use zcash_primitives::transaction::builder::Progress; +use zcash_primitives::transaction::components::orchard::builder::WithOrchard; +use zcash_primitives::transaction::fees::zip317; +use zcash_primitives::transaction::fees::zip317::FeeError; +use zcash_primitives::transaction::fees::FeeRule; use zcash_primitives::{ consensus::BlockHeight, legacy::Script, @@ -38,7 +43,7 @@ use zcash_primitives::{ sapling::prover::TxProver, transaction::{ builder::Builder, - components::{amount::DEFAULT_FEE, Amount, OutPoint, TxOut}, + components::{Amount, OutPoint, TxOut}, }, }; @@ -1160,7 +1165,7 @@ impl LightWallet { // Select notes to cover the target value println!("{}: Selecting notes", now() - start_time); - let target_amount = (Amount::from_u64(total_value).unwrap() + DEFAULT_FEE).unwrap(); + let target_amount = Amount::from_u64(total_value).unwrap(); let target_height = match self.get_target_height().await { Some(h) => BlockHeight::from_u32(h), None => return Err("No blocks in wallet to target, please sync first".to_string()), @@ -1174,7 +1179,7 @@ impl LightWallet { .await .get_taddr_to_secretkey_map(&self.transaction_context.config); - let (orchard_notes, sapling_notes, utxos, selected_value) = self + let (mut orchard_notes, mut sapling_notes, utxos, mut selected_value) = self .select_notes_and_utxos( target_amount, transparent_only, @@ -1221,7 +1226,9 @@ impl LightWallet { }; match address_to_sk.get(&utxo.address) { - Some(sk) => builder.add_transparent_input(*sk, outpoint.clone(), coin.clone()), + Some(sk) => builder.add_transparent_input(*sk, outpoint.clone(), coin.clone()).map_err( + zcash_primitives::transaction::builder::Error::TransparentBuild:: + ), None => { // Something is very wrong let e = format!("Couldn't find the secreykey for taddr {}", utxo.address); @@ -1252,48 +1259,19 @@ impl LightWallet { for selected in orchard_notes.iter() { println!("Adding orchard spend"); - let path = selected.witness.path().unwrap(); - if let Err(e) = builder.add_orchard_spend( - selected.spend_key.clone(), - selected.note.clone(), - orchard::tree::MerklePath::from(( - incrementalmerkletree::Position::from(path.position as usize), - path.auth_path - .iter() - .map(|(node, _)| node.clone()) - .collect(), - )), - ) { + if let Err(e) = builder + .add_orchard_spend::( + selected.spend_key.clone(), + selected.note.clone(), + orchard_witness_to_merkle_path(&selected.witness), + ) + { let e = format!("Error adding note: {:?}", e); error!("{}", e); return Err(e); } } - //TODO: Send change to orchard instead of sapling - // If no Sapling notes were added, add the change address manually. That is, - // send the change to our sapling address manually. Note that if a sapling note was spent, - // the builder will automatically send change to that address - if sapling_notes.len() == 0 { - builder.send_change_to( - zcash_primitives::keys::OutgoingViewingKey::from( - &*self.unified_spend_capability().read().await, - ), - self.unified_spend_capability() - .read() - .await - .addresses() - .iter() - .find_map(|address| address.sapling()) - .ok_or( - "No sapling receivers in wallet to receive change!\n\ - please add an address with a sapling component" - .to_string(), - )? - .clone(), - ); - } - // We'll use the first ovk to encrypt outgoing transactions let sapling_ovk = zcash_primitives::keys::OutgoingViewingKey::from( &*self.unified_spend_capability().read().await, @@ -1302,14 +1280,15 @@ impl LightWallet { orchard::keys::OutgoingViewingKey::from(&*self.unified_spend_capability().read().await); let mut total_z_recipients = 0u32; - for (recipient_address, value, memo) in recipients { + let mut total_o_recipients = 0; + for (recipient_address, value, memo) in recipients.iter() { // Compute memo if it exists let validated_memo = match memo { None => MemoBytes::from(Memo::Empty), Some(s) => { // If the string starts with an "0x", and contains only hex chars ([a-f0-9]+) then // interpret it as a hex - match utils::interpret_memo_string(s) { + match utils::interpret_memo_string(s.clone()) { Ok(m) => m, Err(e) => { error!("{}", e); @@ -1324,27 +1303,34 @@ impl LightWallet { if let Err(e) = match recipient_address { address::RecipientAddress::Shielded(to) => { total_z_recipients += 1; - builder.add_sapling_output(Some(sapling_ovk), to.clone(), value, validated_memo) - } - address::RecipientAddress::Transparent(to) => { - builder.add_transparent_output(&to, value) + builder + .add_sapling_output(Some(sapling_ovk), to.clone(), *value, validated_memo) + .map_err( + zcash_primitives::transaction::builder::Error::SaplingBuild::, + ) } + address::RecipientAddress::Transparent(to) => builder + .add_transparent_output(&to, *value) + .map_err(zcash_primitives::transaction::builder::Error::TransparentBuild), address::RecipientAddress::Unified(ua) => { if let Some(orchard_addr) = ua.orchard() { - builder.add_orchard_output( + total_o_recipients += 1; + builder.add_orchard_output::( Some(orchard_ovk.clone()), orchard_addr.clone(), - u64::from(value), + u64::from(*value), validated_memo, ) } else if let Some(sapling_addr) = ua.sapling() { total_z_recipients += 1; - builder.add_sapling_output( - Some(sapling_ovk), - sapling_addr.clone(), - value, - validated_memo, - ) + builder + .add_sapling_output( + Some(sapling_ovk), + sapling_addr.clone(), + *value, + validated_memo, + ) + .map_err(zcash_primitives::transaction::builder::Error::SaplingBuild) } else { return Err("Received UA with no Orchard or Sapling receiver".to_string()); } @@ -1356,6 +1342,205 @@ impl LightWallet { } } + let fee_rule = zcash_primitives::transaction::fees::zip317::FeeRule::standard(); + + let mut fee_estimate = fee_rule + .fee_required( + &self.transaction_context.config.chain, + target_height, + builder.transparent_inputs(), + builder.transparent_outputs(), + // The transaction builder will arity pad, which we + // need to account for + match builder.sapling_inputs().len() { + 1 => 2, + n => n, + }, + match builder.sapling_outputs().len() { + 1 => 2, + n => n, + }, + match max(orchard_notes.len(), total_o_recipients + 1) { + 1 => 2, + n => n, + }, + ) + .map_err(|e| e.to_string())?; + + if (fee_estimate + target_amount).unwrap() > selected_value { + if max(orchard_notes.len(), total_o_recipients) + + max(sapling_notes.len(), total_z_recipients as usize) + < 2 + || sapling_notes.len() == 1 + || sapling_notes.len() < total_z_recipients as usize + { + if self + .add_extra_sapling_note_for_fee( + &mut sapling_notes, + target_amount, + &mut selected_value, + fee_estimate, + &mut builder, + ) + .await? + .is_some() + { + fee_estimate = fee_rule + .fee_required( + &self.transaction_context.config.chain, + target_height, + builder.transparent_inputs(), + builder.transparent_outputs(), + // The transaction builder will arity pad, which we + // need to account for + match builder.sapling_inputs().len() { + 1 => 2, + n => n, + }, + match builder.sapling_outputs().len() { + 1 => 2, + n => n, + }, + match max(orchard_notes.len(), total_o_recipients + 1) { + 1 => 2, + n => n, + }, + ) + .map_err(|e| e.to_string())?; + } else { + let free_input: bool = max(orchard_notes.len(), total_o_recipients) + + max(sapling_notes.len(), total_z_recipients as usize) + < 2 + || orchard_notes.len() < 2 + // We haven't added our orchard change output yet + || orchard_notes.len() < total_o_recipients + 1; + if self + .add_extra_orchard_note_for_fee( + &mut orchard_notes, + target_amount, + &mut selected_value, + if free_input { + fee_estimate + } else { + (fee_estimate + fee_rule.marginal_fee()).unwrap() + }, + &mut builder, + ) + .await? + .is_some() + { + fee_estimate = fee_rule + .fee_required( + &self.transaction_context.config.chain, + target_height, + builder.transparent_inputs(), + builder.transparent_outputs(), + // The transaction builder will arity pad, which we + // need to account for + match builder.sapling_inputs().len() { + 1 => 2, + n => n, + }, + match builder.sapling_outputs().len() { + 1 => 2, + n => n, + }, + match max(orchard_notes.len(), total_o_recipients + 1) { + 1 => 2, + n => n, + }, + ) + .map_err(|e| e.to_string())?; + } else { + if self + .add_extra_sapling_note_for_fee( + &mut sapling_notes, + target_amount, + &mut selected_value, + (fee_estimate + fee_rule.marginal_fee()).unwrap(), + &mut builder, + ) + .await? + .is_some() + { + fee_estimate = fee_rule + .fee_required( + &self.transaction_context.config.chain, + target_height, + builder.transparent_inputs(), + builder.transparent_outputs(), + // The transaction builder will arity pad, which we + // need to account for + match builder.sapling_inputs().len() { + 1 => 2, + n => n, + }, + match builder.sapling_outputs().len() { + 1 => 2, + n => n, + }, + match max(orchard_notes.len(), total_o_recipients + 1) { + 1 => 2, + n => n, + }, + ) + .map_err(|e| e.to_string())?; + } else { + return Err( + "Can't cover transaction fee with a single additional note. \ + Either there are insufficient funds in the wallet to cover \ + the fee, or all remaining notes are very small. It is \ + possible that multiple notes could be added to cover the \ + fee, but as fees scale with transaction size, this could \ + lead to extreme fees. As such, implementing such a mechansm \ + is low-priority." + .to_string(), + ); + } + } + } + } + } + + let destination_uas = recipients + .iter() + .filter_map(|recipient| match recipient.0 { + address::RecipientAddress::Shielded(_) => None, + address::RecipientAddress::Transparent(_) => None, + address::RecipientAddress::Unified(ref ua) => Some(ua.clone()), + }) + .collect::>(); + let mut uas_vec = Vec::new(); + #[allow(unused_must_use)] + for ua in destination_uas { + let ua_bytes = ua.encode(&self.transaction_context.config.chain); + if ua_bytes.len() + uas_vec.len() > 511 { + break; + } + // This is only used by future consumers, so we don't really care if this + // goes wrong, hence the allow(unused_must_use) + uas_vec.write(ua_bytes.as_bytes()); + } + uas_vec.truncate(511); + let mut uas_bytes = [0u8; 511]; + uas_bytes[..uas_vec.len()].copy_from_slice(uas_vec.as_slice()); + + dbg!(selected_value, target_amount, fee_estimate); + if let Err(e) = builder.add_orchard_output::( + Some(orchard_ovk.clone()), + *self.unified_spend_capability().read().await.addresses()[0] + .orchard() + .unwrap(), + dbg!(u64::from(selected_value) - u64::from(target_amount) - u64::from(fee_estimate)), + // Here we store the uas we sent to in the memo field. We don't use these yet, + // but they will eventually be used during rescan, to recover the full UA we sent to. + MemoBytes::from(Memo::Arbitrary(Box::new(uas_bytes))), + ) { + let e = format!("Error adding change output: {:?}", e); + error!("{}", e); + return Err(e); + } + // Set up a channel to recieve updates on the progress of building the transaction. let (transmitter, receiver) = channel::(); let progress = self.send_progress.clone(); @@ -1387,7 +1572,7 @@ impl LightWallet { println!("{}: Building transaction", now() - start_time); builder.with_progress_notifier(transmitter); - let (transaction, _) = match builder.build(&prover) { + let (transaction, _) = match builder.build(&prover, &fee_rule) { Ok(res) => res, Err(e) => { let e = format!("Error creating transaction: {:?}", e); @@ -1477,6 +1662,86 @@ impl LightWallet { Ok((transaction_id, raw_transaction)) } + async fn add_extra_sapling_note_for_fee( + &self, + sapling_notes: &mut Vec, + target_amount: Amount, + selected_value: &mut Amount, + fee_estimate: Amount, + builder: &mut Builder<'_, zingoconfig::ChainType, OsRng, WithOrchard>, + ) -> Result, String> { + match self + .get_all_domain_specific_notes::>() + .await + .into_iter() + .filter(|spendable_note| !sapling_notes.contains(spendable_note)) + .filter(|spendable_note| { + Amount::from_u64(spendable_note.note.value).unwrap() + >= (fee_estimate + target_amount - *selected_value).unwrap() + }) + .min_by_key(|spendable_note| Amount::from_u64(spendable_note.note.value).unwrap()) + { + Some(fee_paying_extra_note) => { + if let Err(e) = builder.add_sapling_spend( + fee_paying_extra_note.extsk.clone(), + fee_paying_extra_note.diversifier, + fee_paying_extra_note.note.clone(), + fee_paying_extra_note.witness.path().unwrap(), + ) { + let e = format!("Error adding note: {:?}", e); + error!("{}", e); + return Err(e); + }; + *selected_value = (*selected_value + + Amount::from_u64(fee_paying_extra_note.note.value).unwrap()) + .unwrap(); + sapling_notes.push(fee_paying_extra_note); + Ok(Some(())) + } + None => Ok(None), + } + } + + async fn add_extra_orchard_note_for_fee( + &self, + sapling_notes: &mut Vec, + target_amount: Amount, + selected_value: &mut Amount, + fee_estimate: Amount, + builder: &mut Builder<'_, zingoconfig::ChainType, OsRng, WithOrchard>, + ) -> Result, String> { + match self + .get_all_domain_specific_notes::() + .await + .into_iter() + .filter(|spendable_note| !sapling_notes.contains(spendable_note)) + .filter(|spendable_note| { + Amount::from_u64(spendable_note.note.value().inner()).unwrap() + >= (fee_estimate + target_amount - *selected_value).unwrap() + }) + .min_by_key(|spendable_note| { + Amount::from_u64(spendable_note.note.value().inner()).unwrap() + }) { + Some(fee_paying_extra_note) => { + if let Err(e) = builder.add_orchard_spend::( + fee_paying_extra_note.spend_key.clone(), + fee_paying_extra_note.note.clone(), + orchard_witness_to_merkle_path(&fee_paying_extra_note.witness), + ) { + let e = format!("Error adding note: {:?}", e); + error!("{}", e); + return Err(e); + }; + *selected_value = (*selected_value + + Amount::from_u64(fee_paying_extra_note.note.value().inner()).unwrap()) + .unwrap(); + sapling_notes.push(fee_paying_extra_note); + Ok(Some(())) + } + None => Ok(None), + } + } + async fn get_orchard_anchor( &self, orchard_notes: &[SpendableOrchardNote], @@ -1531,6 +1796,21 @@ fn decode_orchard_spending_key( } } +fn orchard_witness_to_merkle_path( + witness: &zcash_primitives::merkle_tree::IncrementalWitness, +) -> orchard::tree::MerklePath { + orchard::tree::MerklePath::from(( + incrementalmerkletree::Position::from(witness.path().unwrap().position as usize), + witness + .path() + .unwrap() + .auth_path + .iter() + .map(|(node, _)| node.clone()) + .collect(), + )) +} + #[cfg(test)] mod test { use orchard::tree::MerkleHashOrchard; diff --git a/lib/src/wallet/data.rs b/lib/src/wallet/data.rs index 49cc185970..b297b54040 100644 --- a/lib/src/wallet/data.rs +++ b/lib/src/wallet/data.rs @@ -726,6 +726,14 @@ pub struct SpendableSaplingNote { pub extsk: ExtendedSpendingKey, } +impl PartialEq for SpendableSaplingNote { + fn eq(&self, other: &Self) -> bool { + self.note == other.note + } +} + +impl Eq for SpendableSaplingNote {} + pub struct SpendableOrchardNote { pub transaction_id: TxId, pub nullifier: OrchardNullifier, @@ -735,6 +743,14 @@ pub struct SpendableOrchardNote { pub spend_key: OrchardSpendingKey, } +impl PartialEq for SpendableOrchardNote { + fn eq(&self, other: &Self) -> bool { + self.note == other.note + } +} + +impl Eq for SpendableOrchardNote {} + // Struct that tracks the latest and historical price of ZEC in the wallet #[derive(Clone, Debug)] pub struct WalletZecPriceInfo { diff --git a/lib/src/wallet/keys.rs b/lib/src/wallet/keys.rs index 1c8b33bff6..e6bc020abc 100644 --- a/lib/src/wallet/keys.rs +++ b/lib/src/wallet/keys.rs @@ -97,7 +97,7 @@ pub fn get_zaddr_from_bip39seed( ChildIndex::Hardened(pos), ], ); - let extfvk = ExtendedFullViewingKey::from(&extsk); + let extfvk = extsk.to_extended_full_viewing_key(); let address = extfvk.default_address().1; (extsk, extfvk, address) diff --git a/lib/src/wallet/keys/unified.rs b/lib/src/wallet/keys/unified.rs index cca419453b..b639f6c225 100644 --- a/lib/src/wallet/keys/unified.rs +++ b/lib/src/wallet/keys/unified.rs @@ -105,10 +105,11 @@ impl UnifiedSpendCapability { } else { None }; - let (mut new_index, address) = - zcash_primitives::zip32::ExtendedFullViewingKey::from(&self.sapling_key) - .find_address(self.next_sapling_diversifier_index) - .expect("Diversifier index overflow"); + let (mut new_index, address) = self + .sapling_key + .to_diversifiable_full_viewing_key() + .find_address(self.next_sapling_diversifier_index) + .expect("Diversifier index overflow"); new_index.increment().expect("Diversifier index overflow"); self.next_sapling_diversifier_index = new_index; let sapling_receiver = if desired_receivers.sapling { @@ -315,8 +316,9 @@ impl From<&UnifiedSpendCapability> for orchard::keys::IncomingViewingKey { impl From<&UnifiedSpendCapability> for zcash_primitives::sapling::SaplingIvk { fn from(usc: &UnifiedSpendCapability) -> Self { - zcash_primitives::zip32::ExtendedFullViewingKey::from(&usc.sapling_key) - .fvk + usc.sapling_key + .to_diversifiable_full_viewing_key() + .fvk() .vk .ivk() } @@ -329,7 +331,7 @@ impl From<&UnifiedSpendCapability> for orchard::keys::FullViewingKey { impl From<&UnifiedSpendCapability> for zcash_primitives::zip32::ExtendedFullViewingKey { fn from(usc: &UnifiedSpendCapability) -> Self { - zcash_primitives::zip32::ExtendedFullViewingKey::from(&usc.sapling_key) + usc.sapling_key.to_extended_full_viewing_key() } } impl From<&UnifiedSpendCapability> for orchard::keys::OutgoingViewingKey { @@ -340,8 +342,9 @@ impl From<&UnifiedSpendCapability> for orchard::keys::OutgoingViewingKey { impl From<&UnifiedSpendCapability> for zcash_primitives::keys::OutgoingViewingKey { fn from(usc: &UnifiedSpendCapability) -> Self { - zcash_primitives::zip32::ExtendedFullViewingKey::from(&usc.sapling_key) - .fvk + usc.sapling_key + .to_diversifiable_full_viewing_key() + .fvk() .ovk } } diff --git a/lib/src/wallet/message.rs b/lib/src/wallet/message.rs index 40d114187b..aaea1c240f 100644 --- a/lib/src/wallet/message.rs +++ b/lib/src/wallet/message.rs @@ -16,7 +16,9 @@ use zcash_primitives::{ keys::OutgoingViewingKey, memo::Memo, sapling::{ - note_encryption::{prf_ock, try_sapling_note_decryption, SaplingDomain}, + note_encryption::{ + prf_ock, try_sapling_note_decryption, PreparedIncomingViewingKey, SaplingDomain, + }, PaymentAddress, Rseed, SaplingIvk, ValueCommitment, }, }; @@ -202,7 +204,7 @@ impl Message { match try_sapling_note_decryption( &MAIN_NETWORK, BlockHeight::from_u32(1_100_000), - &ivk, + &PreparedIncomingViewingKey::new(&ivk), &Unspendable { cmu_bytes, epk_bytes, @@ -231,7 +233,7 @@ pub mod tests { use zcash_primitives::{ memo::Memo, sapling::{PaymentAddress, Rseed, SaplingIvk}, - zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + zip32::ExtendedSpendingKey, }; use super::{Message, ENC_CIPHERTEXT_SIZE}; @@ -242,10 +244,10 @@ pub mod tests { rng.fill(&mut seed); let extsk = ExtendedSpendingKey::master(&seed); - let ivk = ExtendedFullViewingKey::from(&extsk); - let (_, addr) = ivk.default_address(); + let dfvk = extsk.to_diversifiable_full_viewing_key(); + let (_, addr) = dfvk.default_address(); - (extsk, ivk.fvk.vk.ivk(), addr) + (extsk, dfvk.fvk().vk.ivk(), addr) } #[test] diff --git a/lib/src/wallet/traits.rs b/lib/src/wallet/traits.rs index 4ae95d0186..98cb448d03 100644 --- a/lib/src/wallet/traits.rs +++ b/lib/src/wallet/traits.rs @@ -26,7 +26,7 @@ use orchard::{ tree::MerkleHashOrchard, Action, Address as OrchardAddress, }; -use subtle::CtOption; + use zcash_address::unified::{self, Encoding as _, Receiver}; use zcash_client_backend::{address::UnifiedAddress, encoding::encode_payment_address}; use zcash_encoding::{Optional, Vector}; @@ -179,17 +179,17 @@ pub trait FromCommitment where Self: Sized, { - fn from_commitment(from: &[u8; 32]) -> CtOption; + fn from_commitment(cmu: &[u8; 32]) -> Option; } impl FromCommitment for SaplingNode { - fn from_commitment(from: &[u8; 32]) -> CtOption { - CtOption::new(Self::new(*from), subtle::Choice::from(1)) + fn from_commitment(from: &[u8; 32]) -> Option { + Self::read(from.as_slice()).ok() } } impl FromCommitment for MerkleHashOrchard { - fn from_commitment(from: &[u8; 32]) -> CtOption { - Self::from_bytes(from) + fn from_commitment(cmu: &[u8; 32]) -> Option { + Option::from(Self::from_bytes(cmu)) } } @@ -794,7 +794,7 @@ impl DomainWalletExt

for SaplingDomain

{ Self::Fvk::from(usc) } fn usc_to_ivk(usc: &UnifiedSpendCapability) -> Self::IncomingViewingKey { - Self::IncomingViewingKey::from(usc) + Self::IncomingViewingKey::new(&zcash_primitives::sapling::SaplingIvk::from(usc)) } fn usc_to_ovk(usc: &UnifiedSpendCapability) -> Self::OutgoingViewingKey { Self::OutgoingViewingKey::from(usc) @@ -881,7 +881,7 @@ impl Diversifiable for OrchardFullViewingKey { } } -pub trait SpendableNote +pub trait SpendableNote: Eq where P: Parameters, D: DomainWalletExt, @@ -935,6 +935,7 @@ where fn note(&self) -> &D::Note; fn witness(&self) -> &IncrementalWitness<::Node>; fn spend_key(&self) -> &D::SpendingKey; + fn value(&self) -> Amount; } impl SpendableNote> for SpendableSaplingNote { @@ -979,6 +980,10 @@ impl SpendableNote> for SpendableSaplingNote fn spend_key(&self) -> &SaplingExtendedSpendingKey { &self.extsk } + + fn value(&self) -> Amount { + Amount::from_u64(self.note.value).unwrap() + } } impl SpendableNote for SpendableOrchardNote { @@ -1022,6 +1027,10 @@ impl SpendableNote for SpendableOrchardNote { fn spend_key(&self) -> &OrchardSpendingKey { &self.spend_key } + + fn value(&self) -> Amount { + Amount::from_u64(self.note.value().inner()).unwrap() + } } pub trait ReadableWriteable: Sized { @@ -1142,7 +1151,7 @@ impl ReadableWriteable<(OrchardFullViewingKey, OrchardDiversifier)> for OrchardN writer.write_u8(Self::VERSION)?; writer.write_u64::(self.value().inner())?; writer.write_all(&self.rho().to_bytes())?; - writer.write_all(self.random_seed().as_bytes())?; + writer.write_all(self.rseed().as_bytes())?; Ok(()) } }