diff --git a/.cargo/config.offline b/.cargo/config.offline index a6339df37f3..28c93ea74d9 100644 --- a/.cargo/config.offline +++ b/.cargo/config.offline @@ -1,5 +1,28 @@ +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" + [source.crates-io] replace-with = "vendored-sources" +[source."https://github.com/zcash/librustzcash.git"] +git = "https://github.com/zcash/librustzcash.git" +rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" +replace-with = "vendored-sources" + +[source."https://github.com/zcash/orchard.git"] +git = "https://github.com/zcash/orchard.git" +rev = "f4587f790d7317df85a9ee77ce693a06ed6d8d02" +replace-with = "vendored-sources" + +[source."https://github.com/zcash/incrementalmerkletree.git"] +git = "https://github.com/zcash/incrementalmerkletree.git" +rev = "62c33e4480a71170b02b9eb7d4b0160194f414ee" +replace-with = "vendored-sources" + +[source."https://github.com/nuttycom/hdwallet.git"] +git = "https://github.com/nuttycom/hdwallet.git" +rev = "576683b9f2865f1118c309017ff36e01f84420c9" +replace-with = "vendored-sources" + [source.vendored-sources] # The directory for this source is set to RUST_VENDORED_SOURCES by src/Makefile.am diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 9a101d34448..44778740470 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -36,7 +36,7 @@ Please provide a general summary of the issue you're experiencing Tell us what should happen ### Actual behaviour + errors -Tell us what happens instead including any noticable error output (any messages +Tell us what happens instead including any noticeable error output (any messages displayed on-screen when e.g. a crash occurred) ### The version of Zcash you were using: diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index d44001af5b2..2c26b85544b 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -34,10 +34,6 @@ jobs: if: always() continue-on-error: true # Temporary until we get this passing - - name: Python UTF-8 encoding - run: ./test/lint/lint-python-utf8-encoding.sh - if: always() - - name: Shebang run: ./test/lint/lint-shebang.sh if: always() @@ -57,20 +53,36 @@ jobs: run: ./test/lint/lint-whitespace.sh if: always() + python: + name: Python + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo python3 -m pip install pyflakes + + - name: Pyflakes + run: pyflakes qa src zcutil + if: always() + + - name: UTF-8 encoding + run: ./test/lint/lint-python-utf8-encoding.sh + if: always() + rust-clippy: - name: Clippy (1.54.0) + name: Clippy (1.59.0) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.54.0 + toolchain: 1.59.0 components: clippy override: true - name: Run clippy uses: actions-rs/clippy-check@v1 with: - name: Clippy (1.54.0) + name: Clippy (1.59.0) token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --all-targets -- -D warnings @@ -81,7 +93,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.54.0 + toolchain: 1.59.0 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 diff --git a/.gitignore b/.gitignore index 601e5351923..3402293c6eb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.exe src/bitcoin src/zcashd +src/zcashd-wallet-tool src/zcash-cli src/zcash-gtest src/zcash-tx diff --git a/COPYING b/COPYING index d7c52f033f3..e6e8c782da6 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,6 @@ -Copyright (c) 2016-2021 The Zcash developers -Copyright (c) 2009-2021 The Bitcoin Core developers -Copyright (c) 2009-2021 Bitcoin Developers +Copyright (c) 2016-2022 The Zcash developers +Copyright (c) 2009-2022 The Bitcoin Core developers +Copyright (c) 2009-2022 Bitcoin Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Cargo.lock b/Cargo.lock index 874259926bc..2b20b6cae13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,55 +3,48 @@ version = 3 [[package]] -name = "aes" -version = "0.6.0" +name = "addr2line" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "aes-soft", - "aesni", - "cipher 0.2.5", + "gimli", ] [[package]] -name = "aes" -version = "0.7.4" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug", -] +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "aes-soft" -version = "0.6.4" +name = "aead" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "cipher 0.2.5", - "opaque-debug", + "generic-array", ] [[package]] -name = "aesni" -version = "0.10.0" +name = "aes" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ - "cipher 0.2.5", + "cfg-if 1.0.0", + "cipher", + "cpufeatures", "opaque-debug", ] [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", "once_cell", "version_check", ] @@ -74,6 +67,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + [[package]] name = "arrayref" version = "0.3.6" @@ -88,24 +87,39 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "atomic-shim" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20fdac7156779a1a30d970e838195558b4810dd06aa69e7c7461bdc518edf9b" +checksum = "67cd4b51d303cf3501c301e8125df442128d3c6d7c69f71b27833d253de47e77" dependencies = [ - "crossbeam", + "crossbeam-utils", ] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] [[package]] name = "base64ct" @@ -121,21 +135,22 @@ checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" [[package]] name = "bellman" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db9a104adfbc817ea09dec27d616c32dbf1d56fd741dcdc2444a3dfa1b9fffd" +checksum = "0944d18a9a37691b87733b39c9360c9950af9aa5f97e2455bc108d8eb64fc1c1" dependencies = [ "bitvec", - "blake2s_simd", + "blake2s_simd 0.5.11", "byteorder", - "crossbeam", + "crossbeam-channel", "ff", - "futures", - "futures-cpupool", "group", + "lazy_static", + "log", "num_cpus", "pairing", "rand_core 0.6.3", + "rayon", "subtle", ] @@ -151,13 +166,13 @@ dependencies = [ [[package]] name = "bip0039" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4d1925000f9183da41ed95477ea815512b5bb7e06e6c6964986ca077e2b75c" +checksum = "d0830ae4cc96b0617cc912970c2b17e89456fecbf55e8eed53a956f37ab50c41" dependencies = [ "hmac", "pbkdf2", - "rand", + "rand 0.8.5", "sha2", "unicode-normalization", "zeroize", @@ -165,9 +180,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" @@ -192,6 +207,17 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake2b_simd" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "constant_time_eq", +] + [[package]] name = "blake2s_simd" version = "0.5.11" @@ -203,6 +229,17 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake2s_simd" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -213,13 +250,12 @@ dependencies = [ ] [[package]] -name = "block-modes" -version = "0.7.0" +name = "block-buffer" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "block-padding", - "cipher 0.2.5", + "generic-array", ] [[package]] @@ -229,7 +265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" dependencies = [ "block-padding", - "cipher 0.3.0", + "cipher", ] [[package]] @@ -240,9 +276,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bls12_381" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397" +checksum = "6d28daeeded7949f1c7c72693377c98473b00be0aa0023760a84a300e4e7c74b" dependencies = [ "ff", "group", @@ -260,6 +296,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + [[package]] name = "byteorder" version = "1.4.3" @@ -268,9 +310,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -285,25 +333,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chrono" -version = "0.4.19" +name = "chacha20" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi", + "cfg-if 1.0.0", + "cipher", + "cpufeatures", + "zeroize", ] [[package]] -name = "cipher" -version = "0.2.5" +name = "chacha20poly1305" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" dependencies = [ - "generic-array", + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", ] [[package]] @@ -316,63 +367,41 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "cpufeatures" -version = "0.1.5" +name = "clearscreen" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" +checksum = "a7ed49b0e894fe6264a58496c7ec4e9d3c46f66b59efae527cd5bee429d0a418" dependencies = [ - "libc", + "nix", + "terminfo", + "thiserror", + "which", + "winapi", ] [[package]] -name = "crossbeam" -version = "0.7.3" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-channel 0.4.4", - "crossbeam-deque 0.7.3", - "crossbeam-epoch 0.8.2", - "crossbeam-queue", - "crossbeam-utils 0.7.2", -] +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] -name = "crossbeam-channel" -version = "0.4.4" +name = "cpufeatures" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] @@ -382,65 +411,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.8.2" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "lazy_static", - "memoffset 0.6.4", + "memoffset", "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ "cfg-if 1.0.0", "lazy_static", @@ -453,48 +445,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" [[package]] -name = "crypto-mac" -version = "0.11.1" +name = "crypto-common" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array", - "subtle", -] - -[[package]] -name = "crypto_api" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" - -[[package]] -name = "crypto_api_chachapoly" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930b6a026ce9d358a17f9c9046c55d90b14bb847f36b6ebb6b19365d4feffb8" -dependencies = [ - "crypto_api", + "typenum", ] [[package]] -name = "ctor" -version = "0.1.20" +name = "crypto-mac" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "quote", - "syn", + "generic-array", + "subtle", ] [[package]] name = "curve25519-dalek" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "rand_core 0.5.1", "subtle", "zeroize", @@ -519,15 +496,35 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + [[package]] name = "directories" -version = "3.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if 0.1.10", + "dirs-sys", +] + [[package]] name = "dirs-sys" version = "0.3.6" @@ -541,8 +538,9 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "2.2.0" -source = "git+https://github.com/ZcashFoundation/ed25519-zebra.git?rev=d3512400227a362d08367088ffaa9bd4142a69c7#d3512400227a362d08367088ffaa9bd4142a69c7" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" dependencies = [ "curve25519-dalek", "hex", @@ -568,17 +566,25 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "equihash" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ - "blake2b_simd", + "blake2b_simd 1.0.0", "byteorder", ] +[[package]] +name = "f4jumble" +version = "0.0.0" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" +dependencies = [ + "blake2b_simd 1.0.0", +] + [[package]] name = "ff" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63eec06c61e487eecf0f7e6e6372e596a81922c28d33e645d6983ca6493a1af0" +checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" dependencies = [ "bitvec", "rand_core 0.6.3", @@ -593,27 +599,14 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fpe" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25080721bbcd2cd4d765b7d607ea350425fa087ce53cd3e31afcacdab850352" -dependencies = [ - "aes 0.6.0", - "block-modes 0.7.0", - "num-bigint 0.3.2", - "num-integer", - "num-traits", -] - -[[package]] -name = "fpe" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf3e40fc9accc7218e082db8a75aeea244b8f5db73e591774ef93b4276365e6" +checksum = "cd910db5f9ca4dc3116f8c46367825807aa2b942f72565f16b4be0b208a00a9e" dependencies = [ - "block-modes 0.8.1", - "cipher 0.3.0", + "block-modes", + "cipher", "libm", - "num-bigint 0.4.0", + "num-bigint", "num-integer", "num-traits", ] @@ -624,50 +617,33 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures-channel" -version = "0.3.16" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures", - "num_cpus", -] +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-task" -version = "0.3.16" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.16" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "autocfg", "futures-core", "futures-task", "pin-project-lite", @@ -676,9 +652,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -697,20 +673,26 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", "libc", "wasi 0.10.2+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "group" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" dependencies = [ "byteorder", "ff", @@ -718,16 +700,37 @@ dependencies = [ "subtle", ] +[[package]] +name = "gumdrop" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46571f5d540478cf70d2a42dd0d6d8e9f4b9cc7531544b93311e657b86568a0b" +dependencies = [ + "gumdrop_derive", +] + +[[package]] +name = "gumdrop_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "halo2" -version = "0.0.1" -source = "git+https://github.com/zcash/halo2.git?rev=27c4187673a9c6ade13fbdbd4f20955530c22d7f#27c4187673a9c6ade13fbdbd4f20955530c22d7f" +version = "0.1.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f186b85ed81082fb1cf59d52b0111f02915e89a4ac61d292b38d075e570f3a9" dependencies = [ - "blake2b_simd", + "blake2b_simd 0.5.11", "ff", "group", "pasta_curves", - "rand", + "rand 0.8.5", "rayon", ] @@ -740,6 +743,17 @@ dependencies = [ "ahash", ] +[[package]] +name = "hdwallet" +version = "0.3.0" +source = "git+https://github.com/nuttycom/hdwallet?rev=576683b9f2865f1118c309017ff36e01f84420c9#576683b9f2865f1118c309017ff36e01f84420c9" +dependencies = [ + "lazy_static", + "rand_core 0.6.3", + "ring", + "secp256k1", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -762,25 +776,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ "crypto-mac", - "digest", + "digest 0.9.0", ] [[package]] name = "http" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] name = "http-body" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes", "http", @@ -789,9 +803,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -813,9 +827,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project", - "socket2", + "socket2 0.3.19", "tokio", "tower-service", "tracing", @@ -824,17 +838,17 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.1.0" -source = "git+https://github.com/zcash/incrementalmerkletree?rev=b7bd6246122a6e9ace8edb51553fbf5228906cbb#b7bd6246122a6e9ace8edb51553fbf5228906cbb" +version = "0.2.0" +source = "git+https://github.com/zcash/incrementalmerkletree.git?rev=62c33e4480a71170b02b9eb7d4b0160194f414ee#62c33e4480a71170b02b9eb7d4b0160194f414ee" dependencies = [ "serde", ] [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown", @@ -842,9 +856,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] @@ -857,14 +871,30 @@ checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] [[package]] name = "jubjub" -version = "0.7.0" -source = "git+https://github.com/zkcrypto/jubjub.git?rev=96ab4162b83303378eae32a326b54d88b75bffc2#96ab4162b83303378eae32a326b54d88b75bffc2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c" dependencies = [ "bitvec", "bls12_381", @@ -882,56 +912,67 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "librustzcash" version = "0.2.0" dependencies = [ + "anyhow", + "backtrace", "bellman", - "blake2b_simd", - "blake2s_simd", + "blake2b_simd 1.0.0", + "blake2s_simd 1.0.0", "bls12_381", "byteorder", + "clearscreen", "ed25519-zebra", "group", + "gumdrop", "hyper", "incrementalmerkletree", "ipnet", "jubjub", "libc", + "memuse", "metrics", "metrics-exporter-prometheus", "nonempty", "orchard", + "rand 0.8.5", "rand_core 0.6.3", + "secp256k1", + "secrecy", "subtle", "thiserror", + "time", "tokio", "tracing", "tracing-appender", "tracing-core", "tracing-subscriber", "zcash_address", + "zcash_encoding", "zcash_history", "zcash_note_encryption", "zcash_primitives", "zcash_proofs", + "zeroize", ] [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -956,59 +997,52 @@ dependencies = [ [[package]] name = "matchers" -version = "0.0.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ "regex-automata", ] -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" -version = "0.5.6" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] [[package]] -name = "memoffset" -version = "0.6.4" +name = "memuse" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "f69d25cd7528769ad3d897e99eb942774bff8b23165012af490351a44c5b583b" dependencies = [ - "autocfg", + "nonempty", ] [[package]] name = "metrics" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00f42f354a2ed4894db863b3a4db47aef2d2e4435b937221749bd37a8a7aaa8" +checksum = "55586aa936c35f34ba8aa5d97356d554311206e1ce1f9e68fe7b07288e5ad827" dependencies = [ "ahash", "metrics-macros", - "proc-macro-hack", ] [[package]] name = "metrics-exporter-prometheus" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db7052a7cb0b0c0922a1ce499c9e78576763b1d47499ba980a4fe731b96909d" +checksum = "343a5ceb38235928e7a5687412590f07e6d281522dcd9ff51246f8856eef5fe5" dependencies = [ "hyper", "ipnet", @@ -1022,12 +1056,11 @@ dependencies = [ [[package]] name = "metrics-macros" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa72e4a3d157986dd2565c82ecbddcc23941513669a3766b938f6b72eb87f3f" +checksum = "0daa0ab3a0ae956d0e2c1f42511422850e577d36a255357d1a7d08d45ee3a2f1" dependencies = [ "lazy_static", - "proc-macro-hack", "proc-macro2", "quote", "regex", @@ -1036,15 +1069,15 @@ dependencies = [ [[package]] name = "metrics-util" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a58e622a425b7308e73e4390c68b8cb3df4443f2a57495e391b978412531638c" +checksum = "1174223789e331d9d47a4a953dac36e397db60fa8d2a111ac505388c6c7fe32e" dependencies = [ "ahash", "aho-corasick", "atomic-shim", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", + "crossbeam-epoch", + "crossbeam-utils", "dashmap", "hashbrown", "indexmap", @@ -1057,11 +1090,21 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "mio" -version = "0.7.13" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", "log", @@ -1089,36 +1132,48 @@ dependencies = [ ] [[package]] -name = "nonempty" -version = "0.7.0" +name = "nix" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" +checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset", +] [[package]] -name = "ntapi" -version = "0.3.6" +name = "nom" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" dependencies = [ - "winapi", + "memchr", + "version_check", ] [[package]] -name = "num-bigint" -version = "0.3.2" +name = "nonempty" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ - "autocfg", - "num-integer", - "num-traits", + "winapi", ] [[package]] name = "num-bigint" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -1146,19 +1201,37 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "num_threads" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +dependencies = [ + "libc", +] + +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -1168,23 +1241,24 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.0.0" -source = "git+https://github.com/zcash/orchard.git?rev=d0baa18fc6105df4a7847de2b6dc50c5919b3123#d0baa18fc6105df4a7847de2b6dc50c5919b3123" +version = "0.1.0-beta.1" +source = "git+https://github.com/zcash/orchard.git?rev=f4587f790d7317df85a9ee77ce693a06ed6d8d02#f4587f790d7317df85a9ee77ce693a06ed6d8d02" dependencies = [ - "aes 0.6.0", - "arrayvec 0.7.1", + "aes", + "arrayvec 0.7.2", "bigint", "bitvec", - "blake2b_simd", + "blake2b_simd 1.0.0", "ff", - "fpe 0.4.0", + "fpe", "group", "halo2", "incrementalmerkletree", "lazy_static", + "memuse", "nonempty", "pasta_curves", - "rand", + "rand 0.8.5", "reddsa", "serde", "subtle", @@ -1193,27 +1267,27 @@ dependencies = [ [[package]] name = "ordered-float" -version = "2.7.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039f02eb0f69271f26abe3202189275d7aa2258b903cb0281b5de710a2570ff3" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" dependencies = [ "num-traits", ] [[package]] name = "pairing" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de9d09263c9966e8196fe0380c9dbbc7ea114b5cf371ba29004bc1f9c6db7f3" +checksum = "f2e415e349a3006dd7d9482cdab1c980a845bed1377777d768cb693a44540b42" dependencies = [ "group", ] [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -1222,9 +1296,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", @@ -1236,9 +1310,9 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd482dfb8cfba5a93ec0f91e1c0f66967cb2fdc1a8dba646c4f9202c5d05d785" +checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" dependencies = [ "base64ct", "rand_core 0.6.3", @@ -1247,43 +1321,81 @@ dependencies = [ [[package]] name = "pasta_curves" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "179df750e20069669699f537ec0c4bcb248283f45a78b8c66d797fb73dbbb455" +checksum = "d647d91972bad78120fd61e06b225fcda117805c9bbf17676b51bd03a251278b" dependencies = [ - "blake2b_simd", + "blake2b_simd 0.5.11", "ff", "group", "lazy_static", - "rand", + "rand 0.8.5", "static_assertions", "subtle", ] [[package]] name = "pbkdf2" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" dependencies = [ "crypto-mac", "password-hash", ] +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared", + "rand 0.7.3", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -1292,9 +1404,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -1303,46 +1415,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "ppv-lite86" -version = "0.2.10" +name = "poly1305" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] [[package]] -name = "proc-macro-hack" -version = "0.5.19" +name = "ppv-lite86" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quanta" -version = "0.7.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e76a3afdefd0ce2c0363bf3146271e947782240ea617885dd64e56c4de9fb3c9" +checksum = "20afe714292d5e879d8b12740aa223c6a88f118af41870e8b6196e39a02238a8" dependencies = [ - "atomic-shim", - "ctor", + "crossbeam-utils", "libc", "mach", "once_cell", "raw-cpuid", + "wasi 0.10.2+wasi-snapshot-preview1", + "web-sys", "winapi", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -1365,14 +1483,37 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", + "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -1400,23 +1541,32 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", ] [[package]] name = "rand_hc" -version = "0.3.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", ] [[package]] name = "raw-cpuid" -version = "9.1.1" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1733f6f80c9c24268736a501cd00d41a9849b4faa7a9f9334c096e5d10553206" +checksum = "929f54e29691d4e6a9cc558479de70db7aa3d98cd6fe7ab86d7507aa2886b9d2" dependencies = [ "bitflags", ] @@ -1428,7 +1578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ "autocfg", - "crossbeam-deque 0.8.1", + "crossbeam-deque", "either", "rayon-core", ] @@ -1439,21 +1589,22 @@ version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ - "crossbeam-channel 0.5.1", - "crossbeam-deque 0.8.1", - "crossbeam-utils 0.8.5", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", "lazy_static", "num_cpus", ] [[package]] name = "reddsa" -version = "0.0.0" -source = "git+https://github.com/str4d/redjubjub.git?rev=d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2#d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90e2c94bca3445cae0d55dff7370e29c24885d2403a1665ce19c106c79455e6" dependencies = [ - "blake2b_simd", + "blake2b_simd 0.5.11", "byteorder", - "digest", + "digest 0.9.0", "group", "jubjub", "pasta_curves", @@ -1465,9 +1616,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -1478,7 +1629,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", "redox_syscall", ] @@ -1508,26 +1659,83 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1facec54cb5e0dc08553501fa740091086d0259ad0067e0d4103448e4cb22ed3" +dependencies = [ + "digest 0.10.3", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "secp256k1" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d03ceae636d0fed5bae6a7f4f664354c5f4fcedf6eef053fef17e49f837d0a" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +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 = "serde" -version = "1.0.126" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -1536,26 +1744,32 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.5" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] [[package]] name = "sharded-slab" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ "lazy_static", ] +[[package]] +name = "siphasher" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" + [[package]] name = "sketches-ddsketch" version = "0.1.2" @@ -1564,9 +1778,9 @@ checksum = "76a77a8fd93886010f05e7ea0720e569d6d16c65329dbe3ec033bbbccccb017b" [[package]] name = "smallvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" @@ -1579,6 +1793,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1593,9 +1823,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -1604,9 +1834,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", @@ -1620,20 +1850,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "terminfo" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76971977e6121664ec1b960d1313aacfa75642adc93b9d4d53b247bd4cb1747e" +dependencies = [ + "dirs", + "fnv", + "nom", + "phf", + "phf_codegen", +] + [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -1642,28 +1885,36 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] [[package]] name = "time" -version = "0.1.43" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" dependencies = [ + "itoa 1.0.1", "libc", - "winapi", + "num_threads", + "time-macros", ] +[[package]] +name = "time-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" + [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -1676,23 +1927,23 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.9.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ - "autocfg", "libc", "mio", "pin-project-lite", + "socket2 0.4.4", "tokio-macros", "winapi", ] [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -1707,9 +1958,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -1719,20 +1970,20 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9965507e507f12c8901432a33e31131222abac31edd90cabbcf85cf544b7127a" +checksum = "9ab026b18a46ac429e5c98bec10ca06424a97b3ad7b3949d9b4a102fff6623c4" dependencies = [ - "chrono", - "crossbeam-channel 0.5.1", + "crossbeam-channel", + "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" dependencies = [ "proc-macro2", "quote", @@ -1741,26 +1992,27 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" dependencies = [ "lazy_static", + "valuable", ] [[package]] name = "tracing-subscriber" -version = "0.2.19" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" +checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" dependencies = [ "ansi_term", - "chrono", "lazy_static", "matchers", "regex", "sharded-slab", "thread_local", + "time", "tracing", "tracing-core", ] @@ -1773,9 +2025,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-normalization" @@ -1792,11 +2044,33 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" @@ -1820,6 +2094,81 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +dependencies = [ + "either", + "lazy_static", + "libc", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1854,33 +2203,40 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ "bech32", - "blake2b_simd", "bs58", + "f4jumble", + "zcash_encoding", +] + +[[package]] +name = "zcash_encoding" +version = "0.0.0" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" +dependencies = [ + "byteorder", + "nonempty", ] [[package]] name = "zcash_history" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ "bigint", - "blake2b_simd", + "blake2b_simd 1.0.0", "byteorder", ] [[package]] name = "zcash_note_encryption" -version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +version = "0.1.0" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ - "blake2b_simd", - "byteorder", - "crypto_api_chachapoly", - "ff", - "group", + "chacha20", + "chacha20poly1305", "rand_core 0.6.3", "subtle", ] @@ -1888,42 +2244,46 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ - "aes 0.7.4", + "aes", "bip0039", "bitvec", - "blake2b_simd", - "blake2s_simd", + "blake2b_simd 1.0.0", + "blake2s_simd 1.0.0", "bls12_381", + "bs58", "byteorder", - "crypto_api_chachapoly", + "chacha20poly1305", "equihash", "ff", - "fpe 0.5.0", + "fpe", "group", + "hdwallet", "hex", "incrementalmerkletree", "jubjub", "lazy_static", - "log", + "memuse", "nonempty", "orchard", - "pasta_curves", - "rand", + "rand 0.8.5", "rand_core 0.6.3", + "ripemd", + "secp256k1", "sha2", "subtle", + "zcash_encoding", "zcash_note_encryption", ] [[package]] name = "zcash_proofs" version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=19a97f16945c68c33aedcc89f2a4f4d398658b05#19a97f16945c68c33aedcc89f2a4f4d398658b05" +source = "git+https://github.com/zcash/librustzcash.git?rev=67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289#67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" dependencies = [ "bellman", - "blake2b_simd", + "blake2b_simd 1.0.0", "bls12_381", "byteorder", "directories", @@ -1937,18 +2297,18 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.4.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.1.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 6be4d0aa848..9227b9a9fc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,45 +3,59 @@ name = "librustzcash" description = "Rust FFI used by the zcashd binary. Not an official API." version = "0.2.0" authors = [ - "Sean Bowe ", - "Jack Grigg ", - "Jay Graber ", - "Simon Liu " + "Sean Bowe ", + "Jay Graber", + "Jack Grigg ", + "Daira Hopwood ", + "Ying Tong Lai ", + "Simon Liu", + "Kris Nuttycombe ", + "Larry Ruane ", + "Steven Smith " ] homepage = "https://github.com/zcash/zcash" repository = "https://github.com/zcash/zcash" readme = "README.md" license = "MIT OR Apache-2.0" edition = "2018" +rust-version = "1.59" [lib] name = "rustzcash" path = "src/rust/src/rustzcash.rs" crate-type = ["staticlib"] +[[bin]] +name = "zcashd-wallet-tool" +path = "src/rust/bin/wallet_tool.rs" + [dependencies] -bellman = "0.10" -blake2b_simd = "0.5" -blake2s_simd = "0.5" -bls12_381 = "0.5" +bellman = "0.11" +blake2b_simd = "1" +blake2s_simd = "1" +bls12_381 = "0.6" byteorder = "1" -group = "0.10" -incrementalmerkletree = "0.1" +group = "0.11" +incrementalmerkletree = "0.2" libc = "0.2" -jubjub = "0.7" +jubjub = "0.8" +memuse = "0.2" nonempty = "0.7" -orchard = "0.0" +orchard = "=0.1.0-beta.1" +secp256k1 = "0.20" subtle = "2.2" rand_core = "0.6" tracing = "0.1" tracing-core = "0.1" -tracing-appender = "0.1" +tracing-appender = "0.2" zcash_address = "0.0" +zcash_encoding = "0.0" zcash_history = "0.2" -zcash_note_encryption = "0.0" -zcash_primitives = "0.5" +zcash_note_encryption = "0.1" +zcash_primitives = { version = "0.5", features = ["transparent-inputs"] } zcash_proofs = "0.5" -ed25519-zebra = "2.2.0" +ed25519-zebra = "3" +zeroize = "1.4.2" # Metrics hyper = { version = "=0.14.2", default-features = false, features = ["server", "tcp", "http1"] } @@ -51,10 +65,20 @@ metrics-exporter-prometheus = "0.6" thiserror = "1" tokio = { version = "1.0", features = ["rt", "net", "time", "macros"] } +# Wallet tool +# (also depends on thiserror, tracing, and tracing-subscriber with "env-filter" and "fmt" features) +anyhow = "1.0" +backtrace = "0.3" +clearscreen = "1.0" +gumdrop = "0.8" +rand = "0.8" +secrecy = "0.8" +time = { version = "0.3", features = ["formatting", "macros"] } + [dependencies.tracing-subscriber] -version = "0.2.12" +version = "0.3" default-features = false -features = ["ansi", "chrono", "env-filter"] +features = ["ansi", "env-filter", "fmt", "time"] [profile.release] lto = true @@ -62,13 +86,12 @@ panic = 'abort' codegen-units = 1 [patch.crates-io] -ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" } -halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" } -incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" } -jubjub = { git = "https://github.com/zkcrypto/jubjub.git", rev = "96ab4162b83303378eae32a326b54d88b75bffc2" } -orchard = { git = "https://github.com/zcash/orchard.git", rev = "d0baa18fc6105df4a7847de2b6dc50c5919b3123" } -zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" } -zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" } -zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" } -zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" } -zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" } +hdwallet = { git = "https://github.com/nuttycom/hdwallet", rev = "576683b9f2865f1118c309017ff36e01f84420c9" } +incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "62c33e4480a71170b02b9eb7d4b0160194f414ee" } +orchard = { git = "https://github.com/zcash/orchard.git", rev = "f4587f790d7317df85a9ee77ce693a06ed6d8d02" } +zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } +zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } +zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } +zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } +zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "67cb63a5a6b1f2c4cf5a061dbe80e9a71477e289" } diff --git a/Makefile.am b/Makefile.am index a77f7e9802d..d5a8eac6358 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,12 @@ $(BITCOIND_BIN): FORCE $(BITCOIN_CLI_BIN): FORCE $(MAKE) -C src $(@F) +check-security: FORCE + $(MAKE) -C src check-security + +check-symbols: FORCE + $(MAKE) -C src check-symbols + if USE_LCOV baseline.info: diff --git a/README.md b/README.md index 1a84cfe6425..5a276efa5be 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 4.4.1 +Zcash 4.6.0-1 =========== diff --git a/configure.ac b/configure.ac index ac565f294cc..d9181b344c2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,13 +1,13 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 4) -define(_CLIENT_VERSION_MINOR, 4) -define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_MINOR, 6) +define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_BUILD, 51) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2021) +define(_COPYRIGHT_YEAR, 2022) AC_INIT([Zcash],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/zcash/zcash/issues],[zcash]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 91583c1792e..84754abf585 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,45 @@ +zcash (4.6.0+1) stable; urgency=medium + + * 4.6.0-1 release. + + -- Electric Coin Company Wed, 05 Jan 2022 20:18:43 +0000 + +zcash (4.6.0) stable; urgency=medium + + * 4.6.0 release. + + -- Electric Coin Company Thu, 23 Dec 2021 00:35:41 +0000 + +zcash (4.6.0~rc1) stable; urgency=medium + + * 4.6.0-rc1 release. + + -- Electric Coin Company Sat, 18 Dec 2021 04:25:50 +0000 + +zcash (4.5.1+1) stable; urgency=medium + + * 4.5.1-1 release. + + -- Electric Coin Company Fri, 08 Oct 2021 17:03:31 +0000 + +zcash (4.5.1) stable; urgency=medium + + * 4.5.1 release. + + -- Electric Coin Company Wed, 29 Sep 2021 01:49:51 +0100 + +zcash (4.5.0) stable; urgency=medium + + * 4.5.0 release. + + -- Electric Coin Company Thu, 23 Sep 2021 04:20:16 +0100 + +zcash (4.5.0~rc1) stable; urgency=medium + + * 4.5.0-rc1 release. + + -- Electric Coin Company Thu, 16 Sep 2021 23:34:14 +0100 + zcash (4.4.1) stable; urgency=medium * 4.4.1 release. diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 434b7e2f33e..8e1b2d83659 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -4,9 +4,9 @@ Upstream-Contact: Electric Coin Company Source: https://github.com/zcash/zcash Files: * -Copyright: 2016-2021, The Zcash developers - 2009-2021, Bitcoin Core developers - 2009-2021, Bitcoin Developers +Copyright: 2016-2022, The Zcash developers + 2009-2022, Bitcoin Core developers + 2009-2022, Bitcoin Developers License: Expat Comment: The Bitcoin Core developers encompasses the current developers listed on bitcoin.org, as well as the numerous contributors to the project. @@ -71,18 +71,18 @@ Files: build-aux/m4/ax_check_compile_flag.m4 build-aux/m4/ax_check_preproc_flag.m4 Copyright: 2008, Guido U. Draheim 2011, Maarten Bosmans -License: GPLv3-or-later-with-Autoconf-exception +License: GPL-3+ with Autoconf exception Files: build-aux/m4/ax_pthread.m4 Copyright: 2008, Steven G. Johnson 2011, Daniel Richard G. -License: GPLv3-or-later-with-Autoconf-exception +License: GPL-3+ with Autoconf exception Files: qa/zcash/checksec.sh Copyright: 2014-2015, Brian Davis 2013, Robin David 2009-2011, Tobias Klein -License: BSD-3clause-Tobias-Klein +License: BSD-3-clause-Tobias-Klein Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis @@ -92,6 +92,12 @@ Files: depends/sources/boost_*.tar.gz Copyright: 2008 Beman Dawes License: Boost-Software-License-1.0 +Files: depends/sources/clang-llvm-*.tar.xz +Copyright: The libc++ Authors +License: Apache-2 with LLVM exception +Comment: This entry is specifically for the libc++ library. The libc++ Authors + are listed in https://github.com/llvm/llvm-project/blob/main/libcxx/CREDITS.TXT . + Files: depends/sources/db-*.tar.gz Copyright: 1990, 2016 Oracle and/or its affiliates; 1990, 1993, 1994, 1995 The Regents of the University of California; @@ -99,6 +105,18 @@ Copyright: 1990, 2016 Oracle and/or its affiliates; 2000-2005 INRIA, France Telecom License: BDB +Files: depends/sources/libevent-*.tar.gz +Copyright: 2000-2007 Niels Provos + 2007-2012 Niels Provos and Nick Mathewson + 2000 Dug Song + 1993 The Regents of the University of California. + 1998 Todd C. Miller + 2003 Michael A. Davis + 2007 Sun Microsystems + 2002 Christopher Clark + 2006 Maxim Yegorushkin +License: BSD-3-clause + Files: depends/sources/zeromq-*.tar.gz Copyright: 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. @@ -110,11 +128,11 @@ Copyright: 2013 Ericsson AB 2014 AppDynamics Inc. 2015-2016 Brocade Communications Systems Inc. -License: LGPL-with-ZeroMQ-exception +License: LGPL-3+ with ZeroMQ exception Files: depends/sources/google*.tar.gz Copyright: 2008 Google Inc. -License: BSD-3clause-Google +License: BSD-3-clause-Google Files: depends/sources/utfcpp-*.tar.gz Copyright: 2006 Nemanja Trifunovic @@ -122,9 +140,8 @@ License: Boost-Software-License-1.0 Files: depends/*/vendored-sources/halo2/* depends/*/vendored-sources/orchard/* - depends/*/vendored-sources/pasta_curves/* -Copyright: 2020 The Electric Coin Company -License: Bootstrap-Open-Source-Licence-1.0 +Copyright: 2020-2021 The Electric Coin Company +License: BOSL-1+ with Zcash exception Files: src/crypto/ctaes/* Copyright: Copyright (c) 2016 Pieter Wuille @@ -158,9 +175,33 @@ License: GNU-All-permissive-License Files src/leveldb/* Copyright: 2011, The LevelDB Authors -License: BSD-3clause-Google +License: BSD-3-clause-Google Comment: The LevelDB Authors are listed in src/leveldb/AUTHORS. +License: Apache-2 with LLVM exception + ============================================================================== + The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: + ============================================================================== + . + On Debian systems, the full text of the Apache License v2.0 can be found in the + file `/usr/share/common-licenses/Apache-2.0`. + . + ---- LLVM Exceptions to the Apache 2.0 License ---- + . + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into an Object form of such source code, you + may redistribute such embedded portions in such Object form without complying + with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + . + In addition, if you combine or link compiled forms of this Software with + software that is licensed under the GPLv2 ("Combined Software") and if a + court of competent jurisdiction determines that the patent provision (Section + 3), the indemnity provision (Section 9) or other Section of the License + conflicts with the conditions of the GPLv2, you may retroactively and + prospectively choose to deem waived or otherwise exclude such Section(s) of + the License, but only in their entirety and only with respect to the Combined + Software. + License: Boost-Software-License-1.0 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by @@ -943,7 +984,7 @@ License: BDB * THE POSSIBILITY OF SUCH DAMAGE. */ -License: BSD-3clause +License: BSD-3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . @@ -987,7 +1028,7 @@ License: Expat TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -License: BSD-3clause-Google +License: BSD-3-clause-Google Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -1014,7 +1055,7 @@ License: BSD-3clause-Google (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -License: BSD-3clause-Tobias-Klein +License: BSD-3-clause-Tobias-Klein Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . @@ -1068,7 +1109,7 @@ Comment: You should have received a copy of the GNU General Public License along with this program. If not, see . -License: LGPL-with-ZeroMQ-exception +License: LGPL-3+ with ZeroMQ exception GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 . @@ -1103,7 +1144,7 @@ License: GNU-All-permissive-License and this notice are preserved. This file is offered as-is, without any warranty. -License: GPLv3-or-later-with-Autoconf-exception +License: GPL-3+ with Autoconf exception This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your @@ -1117,6 +1158,9 @@ License: GPLv3-or-later-with-Autoconf-exception You should have received a copy of the GNU General Public License along with this program. If not, see . . + On Debian systems, the full text of the GNU General Public License + version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. + . As a special exception, the respective Autoconf Macro's copyright owner gives unlimited permission to copy, distribute and modify the configure scripts that are the output of Autoconf when processing the Macro. You @@ -1158,7 +1202,42 @@ License: Expat-with-advertising-clause promote the sale, use or other dealings in this Software without prior written authorization from the authors. -License: Bootstrap-Open-Source-Licence-1.0 +License: BOSL-1+ with Zcash exception + This package ("Original Work") is licensed under the terms of the Bootstrap Open + Source License, version 1.0, or at your option, any later version ("BOSL"). See + the file ./LICENSE-BOSL for the terms of the Bootstrap Open Source Licence, + version 1.0. + . + Only if this Original Work is included as part of the distribution of one of the + following projects ("the Project"): + . + - The Zcash projects published by the Electric Coin Company, + - The Zebra project published by the Zcash Foundation, + . + then License is granted to use this package under the BOSL as modified by the + following clarification and special exception. This exception applies only to + the Original Work when linked or combined with the Project and not to the + Original Work when linked, combined, or included in or with any other software + or project or on a standalone basis. + . + Under the terms of the BOSL, linking or combining this Original Work with + the Project creates a Derivative Work based upon the Original Work and the + terms of the BOSL thus apply to both the Original Work and that Derivative + Work. As a special exception to the BOSL, and to allow this Original Work to + be linked and combined with the Project without having to apply the BOSL to + the other portions of the Project, you are granted permission to link or + combine this Original Work with the Project and to copy and distribute the + resulting work ("Resulting Work") under the open source license applicable + to the Project ("Project License"), provided that any portions of this + Original Work included in the Resulting Work remain subject to the BOSL. For + clarity, you may continue to treat all other portions of the Project under + the Project License, provided that you comply with the BOSL with respect to + the Original Work. If you modify this Original Work, your version of the + Original Work must remain under the BOSL. You may also extend this exception + to your version, but you are not obligated to do so. If you do not wish to + do so, delete this exception statement from your version. + +License: BOSL-1 ======================================================= Bootstrap Open Source Licence ("BOSL") v. 1.0 ======================================================= diff --git a/contrib/devtools/rust-deps-graph.sh b/contrib/devtools/rust-deps-graph.sh new file mode 100755 index 00000000000..7e7804f1ca2 --- /dev/null +++ b/contrib/devtools/rust-deps-graph.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +export LC_ALL=C + +# default arguments are --no-transitive-deps +ARGS="${*:---no-transitive-deps}" +echo "Using args: $ARGS" + +cargo deps $ARGS | dot \ + -Earrowhead=vee \ + -Gratio=0.45 \ + -Gsize=50 \ + -Nheight=0.8 \ + -Nfillcolor=LavenderBlush \ + -Nstyle=filled \ + -Nfontsize=18 \ + -Nmargin=0.05,0.05 \ + -Tpng > rust-dependency-graph.png diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 43c825bdec7..ca1a6e0eaf6 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -189,8 +189,12 @@ def identify_executable(executable): return None if __name__ == '__main__': + args = sys.argv[1:] + allow_no_canary = "--allow-no-canary" in args + files = [arg for arg in args if not arg.startswith("--")] + retval = 0 - for filename in sys.argv[1:]: + for filename in files: try: etype = identify_executable(filename) if etype is None: @@ -201,6 +205,8 @@ def identify_executable(executable): failed = [] warning = [] for (name, func) in CHECKS[etype]: + if name == "Canary" and allow_no_canary: + continue if not func(filename): if name in NONFATAL: warning.append(name) diff --git a/contrib/devtools/update-rust-hashes.sh b/contrib/devtools/update-rust-hashes.sh new file mode 100755 index 00000000000..ad036bebf1e --- /dev/null +++ b/contrib/devtools/update-rust-hashes.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +export LC_ALL=C + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +RUST_PACKAGE="$SCRIPT_DIR/../../depends/packages/native_rust.mk" + +RUST_VERSION=$( cat $RUST_PACKAGE | grep -oP "_version=\K.*" ) + +update_hash() { + url="https://static.rust-lang.org/dist/$1-$RUST_VERSION-$2.tar.gz" + echo "Fetching $url" + hash=$( curl $url | sha256sum | awk '{print $1}' ) + sed -i "/\$(package)_$3_$4=/c\\\$(package)_$3_$4=$hash" $RUST_PACKAGE +} + +update_rust_hash() { + update_hash rust $1 sha256_hash $2 +} + +update_stdlib_hash() { + update_hash rust-std $1 rust_std_sha256_hash $1 +} + +# For native targets +# update_rust_hash RUST_TARGET MAKEFILE_PACKAGE_IDENTIFIER +update_rust_hash aarch64-unknown-linux-gnu aarch64_linux +update_rust_hash x86_64-apple-darwin darwin +update_rust_hash x86_64-unknown-linux-gnu linux +update_rust_hash x86_64-unknown-freebsd freebsd + +# For cross-compilation targets +# update_stdlib_hash RUST_TARGET +update_stdlib_hash aarch64-unknown-linux-gnu +update_stdlib_hash x86_64-apple-darwin +update_stdlib_hash x86_64-pc-windows-gnu +update_stdlib_hash x86_64-unknown-freebsd diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 2c0a127c4dd..c5fd9513ffd 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:10 +FROM debian:11 RUN apt-get update \ && apt-get install -y gnupg2 apt-transport-https curl diff --git a/contrib/docker/README.md b/contrib/docker/README.md index 912604517f2..69f5b7e9d8c 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -76,7 +76,7 @@ mkdir {./zcash-params-dir,./zcash-data-dir} sudo chown -R 2001.2001 {./zcash-params-dir,./zcash-data-dir} docker run -d --name my_zcashd \ -v $(pwd)/zcash-data-dir:/srv/zcashd/.zcash \ - -v $(pwd)/zcash-params-dir/srv/zcashd/.zcash-params \ + -v $(pwd)/zcash-params-dir:/srv/zcashd/.zcash-params \ electriccoinco/zcashd ``` diff --git a/contrib/docker/entrypoint.sh b/contrib/docker/entrypoint.sh index 0dc336851fe..adcbbf8fca3 100755 --- a/contrib/docker/entrypoint.sh +++ b/contrib/docker/entrypoint.sh @@ -40,6 +40,8 @@ if [[ -n "${ZCASHD_RPCPORT}" ]];then ZCASHD_CMD+=" -rpcport=${ZCASHD_RPCPORT}";f if [[ -n "${ZCASHD_ALLOWIP}" ]];then ZCASHD_CMD+=" -rpcallowip=${ZCASHD_ALLOWIP}";fi if [[ -n "${ZCASHD_TXINDEX}" ]];then ZCASHD_CMD+=" -txindex";fi if [[ -n "${ZCASHD_INSIGHTEXPLORER}" ]];then ZCASHD_CMD+=" -insightexplorer";fi +if [[ -n "${ZCASHD_PROMETHEUSPORT}" ]];then ZCASHD_CMD+=" -prometheusport=${ZCASHD_PROMETHEUSPORT}";fi +if [[ -n "${ZCASHD_METRICSIP}" ]];then ZCASHD_CMD+=" -metricsallowip=${ZCASHD_METRICSIP}";fi if [[ -n "${ZCASHD_ZMQPORT}" && -n "${ZCASHD_ZMQBIND}" ]];then ZCASHD_CMD+=" -zmqpubhashblock=tcp://${ZCASHD_ZMQBIND}:${ZCASHD_ZMQPORT}" ZCASHD_CMD+=" -zmqpubhashtx=tcp://${ZCASHD_ZMQBIND}:${ZCASHD_ZMQPORT}" diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 3eddeff5a54..69db0cca2d2 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,9 +1,10 @@ --- -name: "zcash-4.4.1" +name: "zcash-4.6.0-1" enable_cache: true distro: "debian" suites: - "stretch" +- "buster" architectures: - "amd64" packages: @@ -17,6 +18,7 @@ packages: - "g++-multilib" - "git-core" - "libc6-dev" +- "libtinfo5" - "libtool" - "libxml2" - "m4" diff --git a/depends/builders/freebsd.mk b/depends/builders/freebsd.mk index fb2fefe2a2e..7a61043e93e 100644 --- a/depends/builders/freebsd.mk +++ b/depends/builders/freebsd.mk @@ -1,2 +1,4 @@ +build_freebsd_CC = clang +build_freebsd_CXX = clang++ build_freebsd_SHA256SUM = shasum -a 256 build_freebsd_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 7d31a88032c..f64c3474e1c 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,10 +1,9 @@ package=boost -$(package)_version=1_74_0 +$(package)_version=1_78_0 $(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$(subst _,.,$($(package)_version))/source/ $(package)_file_name=boost_$($(package)_version).tar.bz2 -$(package)_sha256_hash=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 +$(package)_sha256_hash=8681f175d4bdb26c52222665793eef08490d7758529330f98d3b29dd0735bccc $(package)_dependencies=native_b2 -$(package)_patches=iostreams-106.patch signals2-noise.patch deprecated-two-arg-allocate.diff ifneq ($(host_os),darwin) $(package)_dependencies+=libcxx @@ -42,9 +41,6 @@ endif endef define $(package)_preprocess_cmds - patch -p2 < $($(package)_patch_dir)/iostreams-106.patch && \ - patch -p2 < $($(package)_patch_dir)/signals2-noise.patch && \ - patch -p2 < $($(package)_patch_dir)/deprecated-two-arg-allocate.diff && \ echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cflags)\" \"$($(package)_cxxflags)\" \"$($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$($(package)_ar)\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef diff --git a/depends/packages/libcxx.mk b/depends/packages/libcxx.mk index 0acb979298f..bbadd228e3f 100644 --- a/depends/packages/libcxx.mk +++ b/depends/packages/libcxx.mk @@ -8,10 +8,10 @@ ifneq ($(host_os),mingw32) $(package)_download_path=$(native_clang_download_path) $(package)_download_file_aarch64_linux=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz $(package)_file_name_aarch64_linux=clang-llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz -$(package)_sha256_hash_aarch64_linux=3d4ad804b7c85007686548cbc917ab067bf17eaedeab43d9eb83d3a683d8e9d4 -$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz -$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz -$(package)_sha256_hash_linux=6b3cc55d3ef413be79785c4dc02828ab3bd6b887872b143e3091692fc6acefe7 +$(package)_sha256_hash_aarch64_linux=15ff2db12683e69e552b6668f7ca49edaa01ce32cb1cbc8f8ed2e887ab291069 +$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz +$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz +$(package)_sha256_hash_linux=84a54c69781ad90615d1b0276a83ff87daaeded99fbc64457c350679df7b4ff0 define $(package)_stage_cmds mkdir -p $($(package)_staging_prefix_dir)/lib && \ @@ -21,14 +21,15 @@ endef else # For Windows cross-compilation, use the MSYS2 binaries. +# Using 13.0.0-3 because 13.0.1-1 has missing `new` and `delete` symbols. $(package)_download_path=https://repo.msys2.org/mingw/x86_64 -$(package)_download_file=mingw-w64-x86_64-libc++-12.0.1-1-any.pkg.tar.zst -$(package)_file_name=mingw-w64-x86_64-libcxx-12.0.1-1-any.pkg.tar.zst -$(package)_sha256_hash=847d86435c35f12b4bc779c91c800a86499ba5c9d419d6ed5e2386c7582c2e81 +$(package)_download_file=mingw-w64-x86_64-libc++-13.0.0-3-any.pkg.tar.zst +$(package)_file_name=mingw-w64-x86_64-libcxx-13.0.0-3-any.pkg.tar.zst +$(package)_sha256_hash=0f8819e88273579f7c9262456c6b8f4d73e1693095c2364d1192c61c5f6a1a4f -$(package)_libcxxabi_download_file=mingw-w64-x86_64-libc++abi-12.0.1-1-any.pkg.tar.zst -$(package)_libcxxabi_file_name=mingw-w64-x86_64-libcxxabi-12.0.1-1-any.pkg.tar.zst -$(package)_libcxxabi_sha256_hash=a60294cb611916f4b9db27b7a6f3d6dc0f75d9006ad6a5bb830427df9b5bc9d2 +$(package)_libcxxabi_download_file=mingw-w64-x86_64-libc++abi-13.0.0-3-any.pkg.tar.zst +$(package)_libcxxabi_file_name=mingw-w64-x86_64-libcxxabi-13.0.0-3-any.pkg.tar.zst +$(package)_libcxxabi_sha256_hash=7224a7252a566938afe91ea8f130682abd29b10e13c9a3c2347af523ca0d7c42 $(package)_extra_sources += $($(package)_libcxxabi_file_name) diff --git a/depends/packages/native_clang.mk b/depends/packages/native_clang.mk index 4db1a43390a..662e088ebf2 100644 --- a/depends/packages/native_clang.mk +++ b/depends/packages/native_clang.mk @@ -1,23 +1,26 @@ package=native_clang -$(package)_major_version=12 -$(package)_version=12.0.1 +$(package)_major_version=13 +$(package)_version=13.0.1 $(package)_download_path=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) $(package)_download_path_linux=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) -$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz -$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz -$(package)_sha256_hash_linux=6b3cc55d3ef413be79785c4dc02828ab3bd6b887872b143e3091692fc6acefe7 -$(package)_download_path_darwin=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_major_version).0.0 -$(package)_download_file_darwin=clang+llvm-$($(package)_major_version).0.0-x86_64-apple-darwin.tar.xz -$(package)_file_name_darwin=clang-llvm-$($(package)_major_version).0.0-x86_64-apple-darwin.tar.xz -$(package)_sha256_hash_darwin=7bc2259bf75c003f644882460fc8e844ddb23b27236fe43a2787870a4cd8ab50 +$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz +$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz +$(package)_sha256_hash_linux=84a54c69781ad90615d1b0276a83ff87daaeded99fbc64457c350679df7b4ff0 +$(package)_download_path_darwin=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) +$(package)_download_file_darwin=clang+llvm-$($(package)_version)-x86_64-apple-darwin.tar.xz +$(package)_file_name_darwin=clang-llvm-$($(package)_version)-x86_64-apple-darwin.tar.xz +$(package)_sha256_hash_darwin=dec02d17698514d0fc7ace8869c38937851c542b02adf102c4e898f027145a4d $(package)_download_path_freebsd=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) -$(package)_download_file_freebsd=clang+llvm-$($(package)_version)-amd64-unknown-freebsd11.tar.xz -$(package)_file_name_freebsd=clang-llvm-$($(package)_version)-amd64-unknown-freebsd11.tar.xz -$(package)_sha256_hash_freebsd=94dfe48d9e483283edbee968056d487a850b30de25258fa48f049cca3ede5db4 - +$(package)_download_file_freebsd=clang+llvm-$($(package)_version)-amd64-unknown-freebsd12.tar.xz +$(package)_file_name_freebsd=clang-llvm-$($(package)_version)-amd64-unknown-freebsd12.tar.xz +$(package)_sha256_hash_freebsd=8101c8d3a920bf930b33987ada5373f43537c5de8c194be0ea10530fd0ad5617 $(package)_download_file_aarch64_linux=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz $(package)_file_name_aarch64_linux=clang-llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz -$(package)_sha256_hash_aarch64_linux=3d4ad804b7c85007686548cbc917ab067bf17eaedeab43d9eb83d3a683d8e9d4 +$(package)_sha256_hash_aarch64_linux=15ff2db12683e69e552b6668f7ca49edaa01ce32cb1cbc8f8ed2e887ab291069 + +ifneq (,$(wildcard /etc/arch-release)) +$(package)_dependencies=native_libtinfo +endif # Ensure we have clang native to the builder, not the target host ifneq ($(canonical_host),$(build)) diff --git a/depends/packages/native_libtinfo.mk b/depends/packages/native_libtinfo.mk new file mode 100644 index 00000000000..d3c200660dd --- /dev/null +++ b/depends/packages/native_libtinfo.mk @@ -0,0 +1,22 @@ +package=native_tinfo +$(package)_version=5.6.0 +$(package)_download_path_linux=http://ftp.debian.org/debian/pool/main/n/ncurses/ +$(package)_download_file_linux=libtinfo5_6.0+20161126-1+deb9u2_amd64.deb +$(package)_file_name_linux=libtinfo5_6.0+20161126-1+deb9u2_amd64.deb +$(package)_sha256_hash_linux=1d249a3193568b5ef785ad8993b9ba6d6fdca0eb359204c2355532b82d25e9f5 + +define $(package)_extract_cmds + mkdir -p $($(package)_extract_dir) && \ + echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + mkdir -p libtinfo5 && \ + ar x --output libtinfo5 $($(package)_source_dir)/$($(package)_file_name) && \ + cd libtinfo5 && \ + tar xf data.tar.xz +endef + +define $(package)_stage_cmds + pwd && \ + mkdir -p $($(package)_staging_prefix_dir)/lib && \ + cp libtinfo5/lib/x86_64-linux-gnu/libtinfo.so.5.9 $($(package)_staging_prefix_dir)/lib/libtinfo.so.5 +endef diff --git a/depends/packages/native_rust.mk b/depends/packages/native_rust.mk index 0cab70854b8..a1901a8fe0c 100644 --- a/depends/packages/native_rust.mk +++ b/depends/packages/native_rust.mk @@ -1,15 +1,14 @@ package=native_rust -$(package)_version=1.54.0 +$(package)_version=1.59.0 $(package)_download_path=https://static.rust-lang.org/dist $(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz -$(package)_sha256_hash_linux=350354495b1d4b6dd2ec7cf96aa9bc61d031951cf667a31e8cf401dc508639e6 +$(package)_sha256_hash_linux=0c1c2da3fa26372e5178123aa5bb0fdcd4933fbad9bfb268ffbd71807182ecae $(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz -$(package)_sha256_hash_darwin=5eb27a4f5f7a4699bc70cf1848e340ddd74e151488bfcb26853fd584958e3d33 +$(package)_sha256_hash_darwin=d82204f536af0c7bfd2ea2213dc46b99911860cfc5517f7321244412ae96f159 $(package)_file_name_freebsd=rust-$($(package)_version)-x86_64-unknown-freebsd.tar.gz -$(package)_sha256_hash_freebsd=026a40470b9fddfbb4abff3546e620eceaa2812ffc13e180bbb9360c01501a16 - +$(package)_sha256_hash_freebsd=83f9c49b6e9025b712fc5d65e49f1b6ad959966534cd39c8dc2ce2c85a6ca484 $(package)_file_name_aarch64_linux=rust-$($(package)_version)-aarch64-unknown-linux-gnu.tar.gz -$(package)_sha256_hash_aarch64_linux=33a50c5366a57aaab43c1c19e4a49ab7d8ffcd99a72925c315fb1f9389139e6f +$(package)_sha256_hash_aarch64_linux=ab5da30a3de5433e26cbc74c56b9d97b569769fc2e456fc54378adc8baaee4f0 # Mapping from GCC canonical hosts to Rust targets # If a mapping is not present, we assume they are identical, unless $host_os is @@ -18,9 +17,10 @@ $(package)_rust_target_x86_64-pc-linux-gnu=x86_64-unknown-linux-gnu $(package)_rust_target_x86_64-w64-mingw32=x86_64-pc-windows-gnu # Mapping from Rust targets to SHA-256 hashes -$(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=2d90cd90734a2d057b2a4eeee36a72d96569fb5fff0ac1e22eeb5fab93e66848 -$(package)_rust_std_sha256_hash_x86_64-apple-darwin=3908ff438cdf39c3f46a103f3a0fa04a0d8add996c87e4290c80f1a766df6a04 -$(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=b3d234211c4255bef6eca800cfb4c44e7779e9d4cb7c0dbe6cd69d8722dd55d6 +$(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=81dbd37919f631f962ac0798111803eb8f06ffde608f0e5dd3682d701cf5566d +$(package)_rust_std_sha256_hash_x86_64-apple-darwin=959af8bafbc9f3916a1d1111d7378fdd7aa459410cdd2d3bbfc2d9d9a6db0683 +$(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=9a67ae84e9e75efb57eeeab617e32379a555de336a30bb74a476e575cd38f63a +$(package)_rust_std_sha256_hash_x86_64-unknown-freebsd=cf5e4303dd7c3b70a738a2336097c9f2189c8b702a89a8c453d83ac0dee4602c define rust_target $(if $($(1)_rust_target_$(2)),$($(1)_rust_target_$(2)),$(if $(findstring darwin,$(3)),x86_64-apple-darwin,$(if $(findstring freebsd,$(3)),x86_64-unknown-freebsd,$(2)))) diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index b7407c8619c..2d85c322685 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -2,6 +2,10 @@ zcash_packages := libsodium utfcpp packages := boost libevent zeromq $(zcash_packages) googletest native_packages := native_clang native_ccache native_rust +ifneq (,$(wildcard /etc/arch-release)) +native_packages += native_libtinfo +endif + wallet_packages=bdb $(host_arch)_$(host_os)_native_packages += native_b2 diff --git a/depends/patches/boost/deprecated-two-arg-allocate.diff b/depends/patches/boost/deprecated-two-arg-allocate.diff deleted file mode 100644 index f9622856636..00000000000 --- a/depends/patches/boost/deprecated-two-arg-allocate.diff +++ /dev/null @@ -1,102 +0,0 @@ -diff -ur orig/include/boost/core/allocator_access.hpp patched/include/boost/core/allocator_access.hpp ---- orig/include/boost/core/allocator_access.hpp 2021-01-18 21:42:05.926895400 +0000 -+++ patched/include/boost/core/allocator_access.hpp 2021-01-18 21:44:26.426895400 +0000 -@@ -11,7 +11,7 @@ - #include - #if !defined(BOOST_NO_CXX11_ALLOCATOR) - #include --#if !defined(BOOST_MSVC) -+#if !defined(BOOST_MSVC) && !defined(BOOST_CLANG) - #include - #else - #include -@@ -49,7 +49,7 @@ - struct allocator_pointer { - typedef typename A::pointer type; - }; --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - struct allocator_pointer { - typedef typename std::allocator_traits::pointer type; -@@ -72,7 +72,7 @@ - struct allocator_const_pointer { - typedef typename A::const_pointer type; - }; --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - struct allocator_const_pointer { - typedef typename std::allocator_traits::const_pointer type; -@@ -137,7 +137,7 @@ - struct allocator_difference_type { - typedef typename A::difference_type type; - }; --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - struct allocator_difference_type { - typedef typename std::allocator_traits::difference_type type; -@@ -161,7 +161,7 @@ - struct allocator_size_type { - typedef typename A::size_type type; - }; --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - struct allocator_size_type { - typedef typename std::allocator_traits::size_type type; -@@ -260,7 +260,7 @@ - struct allocator_rebind { - typedef typename A::template rebind::other type; - }; --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - struct allocator_rebind { - typedef typename std::allocator_traits::template rebind_alloc type; -@@ -313,7 +313,7 @@ - { - return a.allocate(n, h); - } --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - inline typename allocator_pointer::type - allocator_allocate(A& a, typename allocator_size_type::type n, -@@ -400,7 +400,7 @@ - ::new((void*)p) T(v); - } - #endif --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - inline void - allocator_construct(A& a, T* p, Args&&... args) -@@ -449,7 +449,7 @@ - p->~T(); - (void)p; - } --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - inline void - allocator_destroy(A& a, T* p) -@@ -496,7 +496,7 @@ - { - return a.max_size(); - } --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - inline typename allocator_size_type::type - allocator_max_size(const A& a) -@@ -545,7 +545,7 @@ - { - return a; - } --#elif defined(BOOST_MSVC) -+#elif defined(BOOST_MSVC) || defined(BOOST_CLANG) - template - inline A - allocator_select_on_container_copy_construction(const A& a) diff --git a/depends/patches/boost/iostreams-106.patch b/depends/patches/boost/iostreams-106.patch deleted file mode 100644 index dcecd5d0df7..00000000000 --- a/depends/patches/boost/iostreams-106.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4e76f73826fd0a7067b837e4850a9051436f5ec5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= - -Date: Sun, 22 Dec 2019 10:26:38 +0100 -Subject: [PATCH] Fix build on windows with libc++ - -Proposed by @SquallATF in #67 ---- - include/boost/iostreams/detail/config/fpos.hpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/include/boost/iostreams/detail/config/fpos.hpp b/include/boost/iostreams/detail/config/fpos.hpp -index c5dc6cf59..a5835421f 100644 ---- a/include/boost/iostreams/detail/config/fpos.hpp -+++ b/include/boost/iostreams/detail/config/fpos.hpp -@@ -26,7 +26,8 @@ - - # if (defined(_YVALS) || defined(_CPPLIB_VER)) && !defined(__SGI_STL_PORT) && \ - !defined(_STLPORT_VERSION) && !defined(__QNX__) && !defined(_VX_CPU) && !defined(__VXWORKS__) \ -- && !((defined(BOOST_MSVC) || defined(BOOST_CLANG)) && _MSVC_STL_VERSION >= 141) -+ && !((defined(BOOST_MSVC) || defined(BOOST_CLANG)) && _MSVC_STL_VERSION >= 141) \ -+ && !defined(_LIBCPP_VERSION) - /**/ - - #include diff --git a/depends/patches/boost/signals2-noise.patch b/depends/patches/boost/signals2-noise.patch deleted file mode 100644 index e0a9ce48f34..00000000000 --- a/depends/patches/boost/signals2-noise.patch +++ /dev/null @@ -1,23 +0,0 @@ -From fd27423fea5537bc857c1fa14bb0c25b994f77b3 Mon Sep 17 00:00:00 2001 -From: Frank Mori Hess -Date: Mon, 20 Jul 2020 14:17:05 -0400 -Subject: [PATCH] Fix warning about deprecated - boost/function_output_iterator.hpp - ---- - include/boost/signals2/detail/null_output_iterator.hpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/boost/signals2/detail/null_output_iterator.hpp b/include/boost/signals2/detail/null_output_iterator.hpp -index 9e986959..dee4373c 100644 ---- a/include/boost/signals2/detail/null_output_iterator.hpp -+++ b/include/boost/signals2/detail/null_output_iterator.hpp -@@ -11,7 +11,7 @@ - #ifndef BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP - #define BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP - --#include -+#include - - namespace boost - { diff --git a/doc/authors.md b/doc/authors.md index 80fe6602653..c7d8886ddd0 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,33 +1,34 @@ Zcash Contributors ================== -Jack Grigg (1100) +Jack Grigg (1127) Simon Liu (460) Sean Bowe (367) -Daira Hopwood (262) +Daira Hopwood (270) Eirik Ogilvie-Wigley (216) -Wladimir J. van der Laan (133) -Kris Nuttycombe (117) +Kris Nuttycombe (181) +Wladimir J. van der Laan (150) Alfredo Garcia (116) Taylor Hornby (114) -Marshall Gaucher (105) +Marshall Gaucher (111) +Pieter Wuille (102) +Jonas Schnelli (89) Jay Graber (89) -Jonas Schnelli (88) -Pieter Wuille (86) -Marco Falke (80) +Marco Falke (82) Cory Fields (75) -Larry Ruane (60) +Larry Ruane (72) Ying Tong Lai (56) Nathan Wilcox (56) -Matt Corallo (48) +Matt Corallo (52) practicalswift (38) Kevin Gallagher (38) fanquake (36) -Dimitris Apostolou (34) +Dimitris Apostolou (35) Carl Dong (26) +Gregory Maxwell (23) Jorge Timón (22) -Luke Dashjr (20) -Gregory Maxwell (19) +Luke Dashjr (21) +John Newbery (21) Jonathan "Duke" Leto (18) syd (16) Patick Strateman (16) @@ -36,24 +37,24 @@ avnish (14) Per Grön (14) Benjamin Winston (13) Pavel Janík (12) +Patrick Strateman (12) Ariel Gabizon (12) +Suhas Daftuar (11) Paige Peterson (11) Kaz Wesley (11) -John Newbery (11) +Alex Morcos (11) Philip Kaufmann (10) Peter Todd (10) João Barbosa (10) +Charlie O'Keefe (10) nomnombtc (9) Marius Kjærstad (9) +teor (8) kozyilmaz (8) -Suhas Daftuar (8) Jeremy Rubin (8) Jeff Garzik (8) -Charlie O'Keefe (8) Ben Wilson (8) -Patrick Strateman (7) Karl-Johan Alm (7) -Alex Morcos (7) ying tong (6) James O'Beirne (6) David Mercer (6) @@ -63,6 +64,7 @@ Chun Kuan Lee (6) Casey Rodarmor (6) jnewbery (5) ca333 (5) +Sasha (5) MeshCollider (5) Johnathan Corgan (5) George Tankersley (5) @@ -73,7 +75,9 @@ gladcow (4) Zancas Wilcox (4) WO (4) Sjors Provoost (4) +Russell Yanofsky (4) Nate Wilcox (4) +Alex Wied (4) mruddy (3) lpescher (3) isle2983 (3) @@ -84,16 +88,18 @@ Julian Fleischer (3) Jim Posen (3) Jason Davies (3) Evan Klitzke (3) +Ethan Heilman (3) +Eric Lombrozo (3) Danny Willems (3) Anthony Towns (3) Alfie John (3) -Alex Wied (3) whythat (2) rofl0r (2) ptschip (2) noname45688@gmail.com (2) kpcyrd (2) kobake (2) +hexabot (2) face (2) aniemerg (2) Yuri Zhykin (2) @@ -104,7 +110,6 @@ Solar Designer (2) Sebastian Falbesoner (2) Scott (2) S. Matthew English (2) -Russell Yanofsky (2) Robert C. Seacord (2) Pejvan (2) Pavol Rusnak (2) @@ -116,7 +121,6 @@ Joe Turgeon (2) Jeffrey Czyz (2) Jack Gavigan (2) ITH4Coinomia (2) -Ethan Heilman (2) Dagur Valberg Johannsson (2) Bryant Eisenbach (2) Brad Miller (2) @@ -125,13 +129,14 @@ Ben Woosley (2) Amgad Abdelhafez (2) Alex Tsankov (2) Akio Nakamura (2) +Aditya Kulkarni (2) ロハン ダル (1) zathras-crypto (1) vim88 (1) unsystemizer (1) tulip (1) tpantin (1) -teor (1) +sgmoore (1) randy-waterhouse (1) plutoforever (1) murrayn (1) @@ -158,8 +163,10 @@ Vasil Dimov (1) Ulrich Kempken (1) Tom Ritter (1) Tom Harding (1) +Technetium (1) Steven Smith (1) Stephen (1) +Shaul Kfir (1) Ross Nicoll (1) Rod Vagg (1) Robert McLaughlin (1) @@ -197,6 +204,7 @@ Josh Ellithorpe (1) Jonas Nick (1) Jesse Cohen (1) Jeffrey Walton (1) +Janito Vaqueiro Ferreira Filho (1) Jainan-Tandel (1) Igor Cota (1) Ian T (1) @@ -207,7 +215,6 @@ Gregory Sanders (1) Gaurav Rana (1) Forrest Voight (1) Florian Schmaus (1) -Eric Lombrozo (1) Eran Tromer (1) Elliot Olds (1) Dimitris Tsapakidis (1) @@ -232,7 +239,6 @@ Allan Niemerg (1) Alex van der Peet (1) Alex (1) Ahmad Kazi (1) -Aditya Kulkarni (1) Adam Weiss (1) Adam Langley (1) Adam Brown (1) diff --git a/doc/book/src/dev/rust.md b/doc/book/src/dev/rust.md index eb318e8dde3..cae406f3ac8 100644 --- a/doc/book/src/dev/rust.md +++ b/doc/book/src/dev/rust.md @@ -5,7 +5,7 @@ where possible. ## Adding new dependencies in online-Rust mode -The `zcashd` build system pins all dependencies, and in order to faciliate +The `zcashd` build system pins all dependencies, and in order to facilitate deterministic builds, `cargo` is configured to run in offline mode with vendored crates. This means that if, for example, you add the `foobar` crate to `Cargo.toml`, you will likely see an error similar to this: diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index f0161a6ccd4..51ebcfcf104 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. -.TH ZCASH-CLI "1" "June 2021" "zcash-cli v4.4.1" "User Commands" +.TH ZCASH-CLI "1" "January 2022" "zcash-cli v4.6.0-1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v4.4.1 +zcash-cli \- manual page for zcash-cli v4.6.0-1 .SH DESCRIPTION -Zcash RPC client version v4.4.1 +Zcash RPC client version v4.6.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 950fdb3885c..ddb563fcfab 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. -.TH ZCASH-TX "1" "June 2021" "zcash-tx v4.4.1" "User Commands" +.TH ZCASH-TX "1" "January 2022" "zcash-tx v4.6.0-1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v4.4.1 +zcash-tx \- manual page for zcash-tx v4.6.0-1 .SH DESCRIPTION -Zcash zcash\-tx utility version v4.4.1 +Zcash zcash\-tx utility version v4.6.0\-1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index cd103ba400a..cb512e41c7d 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. -.TH ZCASHD "1" "June 2021" "zcashd v4.4.1" "User Commands" +.TH ZCASHD "1" "January 2022" "zcashd v4.6.0-1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v4.4.1 +zcashd \- manual page for zcashd v4.6.0-1 .SH DESCRIPTION -Zcash Daemon version v4.4.1 +Zcash Daemon version v4.6.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -84,7 +84,7 @@ Keep at most unconnectable transactions in memory (default: 100) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-16\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -99,9 +99,13 @@ Reverting this setting requires re\-downloading the entire blockchain. (default: 0 = disable pruning blocks, >550 = target size in MiB to use for block files) .HP +\fB\-reindex\-chainstate\fR +.IP +Rebuild chain state from the currently indexed blocks +.HP \fB\-reindex\fR .IP -Rebuild block chain index from current blk000??.dat files on startup +Rebuild chain state and block index from the blk*.dat files on disk .HP \fB\-sysperms\fR .IP @@ -395,7 +399,7 @@ Debugging/Testing options: Output debugging information (default: 0, supplying is optional). If is not supplied or if = 1, output all debugging information. can be: addrman, alert, bench, -coindb, db, estimatefee, http, libevent, lock, mempool, net, +coindb, db, estimatefee, http, libevent, lock, mempool, mempoolrej, net, partitioncheck, pow, proxy, prune, rand, receiveunsafe, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc). For multiple specific categories use \fB\-debug=\fR multiple times. diff --git a/doc/reduce-traffic.md b/doc/reduce-traffic.md index d9cb6195b9f..e5ccd8ca299 100644 --- a/doc/reduce-traffic.md +++ b/doc/reduce-traffic.md @@ -46,8 +46,8 @@ Be reminded of the effects of this setting. - Fee estimation will no longer work. - It sets the flag "-walletbroadcast" to be "0", only if it is currently unset. - Doing so disables the automatic broadcasting of transactions from wallet. Not - relaying other's transactions could hurt your privacy if used while a wallet + Doing so disables the automatic broadcasting of transactions from the wallet. Not + relaying other's transactions could hurt your privacy if used while the wallet is loaded or if you use the node to broadcast transactions. - If a peer is whitelisted and "-whitelistforcerelay" is set to "1" (which will also set "whitelistrelay" to "1"), we will still receive and relay their transactions. diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..7e0fec699a0 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,94 @@ release-notes at release time) Notable changes =============== +Mnemonic Recovery Phrases +------------------------- + +The zcashd wallet has been modified to support BIP 39, which describes how to +derive the wallet's HD seed from a mnemonic phrase. The mnemonic phrase will +be generated on load of the wallet, or the first time the wallet is unlocked, +and is available via the `z_exportwallet` RPC call. All new addresses produced +by the wallet are now derived from this seed using the HD wallet functionality +described in ZIP 32 and ZIP 316. For users upgrading an existing Zcashd wallet, +it is recommended that the wallet be backed up prior to upgrading to the 4.7.0 +Zcashd release. + +Following the upgrade to 4.7.0, Zcashd will require that the user confirm that +they have backed up their new emergency recovery phrase, which may be obtained +from the output of the `z_exportwallet` RPC call. This confirmation can be +performed manually using the `zcashd-wallet-tool` utility that is supplied +with this release (built or installed in the same directory as `zcashd`). +The wallet will not allow the generation of new addresses until this +confirmation has been performed. It is recommended that after this upgrade, +that funds tied to preexisting addresses be migrated to newly generated +addresses so that all wallet funds are recoverable using the emergency +recovery phrase going forward. If you choose not to migrate funds in this +fashion, you will continue to need to securely back up the entire `wallet.dat` +file to ensure that you do not lose access to existing funds; EXISTING FUNDS +WILL NOT BE RECOVERABLE USING THE EMERGENCY RECOVERY PHRASE UNLESS THEY HAVE +BEEN MOVED TO A NEWLY GENERATED ADDRESS FOLLOWING THE 4.7.0 UPGRADE. + +New RPC Methods +--------------- + +- 'walletconfirmbackup' This newly created API checks a provided emergency + recovery phrase against the wallet's emergency recovery phrase; if the phrases + match then it updates the wallet state to allow the generation of new addresses. + This backup confirmation workflow can be disabled by starting zcashd with + `-requirewalletbackup=false` but this is not recommended unless you know what + you're doing (and have otherwise backed up the wallet's recovery phrase anyway). + For security reasons, this RPC method is not intended for use via zcash-cli + but is provided to enable `zcashd-wallet-tool` and other third-party wallet + interfaces to satisfy the backup confirmation requirement. Use of the + `walletconfirmbackup` API via zcash-cli would risk that the recovery phrase + being confirmed might be leaked via the user's shell history or the system + process table; `zcashd-wallet-tool` is specifically provided to avoid this + problem. +- 'z_getbalanceforviewingkey' This newly created API allows a user to obtain + balance information for funds visible to a Sapling or Unified full + viewing key; if a Sprout viewing key is provided, this method allows + retrieval of the balance only in the case that the wallet controls the + corresponding spending key. + +RPC Changes +----------- + +- The results of the 'dumpwallet' and 'z_exportwallet' RPC methods have been modified + to now include the wallet's newly generated emergency recovery phrase as part of the + exported data. + +- The results of the 'getwalletinfo' RPC have been modified to return two new fields: + `mnemonic_seedfp` and `legacy_seedfp`, the latter of which replaces the field that + was previously named `seedfp`. + +Wallet +------ + +'z_sendmany' +------------ + +- The 'z_sendmany' RPC call no longer permits Sprout recipients in the + list of recipient addresses. Transactions spending Sprout funds will + still result in change being sent back into the Sprout pool, but no + other `Sprout->Sprout` transactions will be constructed by the Zcashd + wallet. + +- The restriction that prohibited `Sprout->Sapling` transactions has been + lifted; however, since such transactions reveal the amount crossing + pool boundaries, they must be explicitly enabled via a parameter to + the 'z_sendmany' call. + +- A new string parameter, `privacyPolicy`, has been added to the list of + arguments accepted by `z_sendmany`. This parameter enables the caller to + control what kind of information they permit `zcashd` to reveal when creating + the transaction. If the transaction can only be created by revealing more + information than the given strategy permits, `z_sendmany` will return an + error. The parameter defaults to `LegacyCompat`, which applies the most + restrictive strategy `FullPrivacy` when a Unified Address is present as the + sender or a recipient, and otherwise preserves existing behaviour (which + corresponds to the `AllowFullyTransparent` policy). + +- Since Sprout outputs are no longer created (with the exception of change) + 'z_sendmany' no longer generates payment disclosures (which were only + available for Sprout outputs) when the `-paymentdisclosure` experimental + feature flag is set. diff --git a/doc/release-notes/release-notes-4.5.0-rc1.md b/doc/release-notes/release-notes-4.5.0-rc1.md new file mode 100644 index 00000000000..c91384283d7 --- /dev/null +++ b/doc/release-notes/release-notes-4.5.0-rc1.md @@ -0,0 +1,311 @@ +Changelog +========= + +Aditya Kulkarni (1): + Sort taddr txns by txindex in addition to height + +Alex Morcos (4): + Store the total sig op count of a tx. + Add a score index to the mempool. + Add TxPriority class and comparator + tidy up CInv::GetCommand + +Daira Hopwood (8): + Improve error message when a block would overfill the Orchard commitment tree. + More precise terminology: "lock free" -> "unlocked" + ZIP 339 support. + Update URL for Boost source download (from dl.bintray.com to boostorg.jfrog.io). + Cargo.toml: use librustzcash after the merge of https://github.com/zcash/librustzcash/pull/424 . + Update unified address test data to take account of HRPs in padding (https://github.com/zcash/librustzcash/pull/419). + Avoid need to cast away const in the C caller of zip339_free_phrase. + Update authors of librustzcash to everyone currently and formerly on Core team (in alphabetical order). + +Eric Lombrozo (2): + Removed ppszTypeName from protocol.cpp + getdata enum issue fix + +Ethan Heilman (1): + Fix typo adddrman to addrman as requested in #8070 + +Ethan Heilman (1): + Remove non-determinism which is breaking net_tests #8069 + +Gregory Maxwell (4): + Eliminate TX trickle bypass, sort TX invs for privacy and priority. + Move bloom and feerate filtering to just prior to tx sending. + Do not use mempool for GETDATA for tx accepted after the last mempool req. + Defer inserting into maprelay until just before relaying. + +Jack Grigg (109): + Re-include reading blocks from disk in block connection benchmark + cargo update + Migrate to latest zcash_* crates + metrics 0.16 and metrics-exporter-prometheus 0.5 + Implement ZIP 216 consensus rules + Extract SpendDescriptionV5 and OutputDescriptionV5 classes + rust: Enable C++ streams to be passed into Rust code + ZIP 225 tx format constants + v5 transaction format parser + contrib: Add BOSL to contrib/debian/copyright + Remove early return logic from transaction parsing + rust: Document read_callback_t and write_callback_t + CTransaction: Make new ZIP 225 fields non-const and private + ZIP 244 transaction digests + ZIP 244 signature digests + ZIP 244 hashAuthDataRoot computation + Fix tests that assume CTxOuts can be "null" + test: Generate valid Sapling types + test: Small fixes to sighash test vector generation + test: Regenerate sighash.json after generator fixes + Throw an exception instead of asserting if Rust tx parser fails + CI: Publish correct book directory + CI: Build book with latest mdbook + rust: Documentation improvements to FFI methods + Implement Orchard authorization batch validator + Implement Orchard signature validation consensus rules + rust: Fix patched dependencies + book: Add dev guide page about Rust dependencies + Rename hashLightClientRoot to hashBlockCommitments in block header + ZIP 244 hashBlockCommitments implementation + test: Check for valid hashBlockCommitments construction post-NU5 + Skip hashBlockCommitments check when testing block templates + test: Check hashBlockCommitments before, at, and after NU5 activation + ConnectBlock: Check NU activation when deriving block commitments + Copy authDigest in CTransaction::operator=(const CTransaction &tx) + rust: Move history tree FFI logic into a module + rust: Migrate to zcash_history with versioned trees + rust: Move history tree FFI declarations into a separate header + test: Use valid consensus branch IDs in history tree tests + Use V2 history trees from NU5 onward + test: Check history trees across Canopy and NU5 activations + rpc: Document getblock RPC finalorchardroot field, omit before NU5 + rust: Document some requirements for history tree FFI methods + test: Add test case for popping from an empty history tree + Implement Orchard pool value tracking + rust: Load Orchard circuit parameters at startup + Check Orchard bundle-specific consensus rules, i.e. proofs + test: Update CCoinsViewTest with changes to CCoinsView interface + Include Orchard bundle in transaction dynamic usage + ZIP 203: Enforce coinbase nExpiryHeight consensus rule from NU5 + test: Check for updated empty-tx reject messages in transaction tests + test: Fix OverwinterExpiryHeight test after ZIP 203 contextual changes + miner: Set coinbase expiry height to block height from NU5 activation + Introduce libzcash::RawAddress type + Use `libzcash::RawAddress` in `CWallet::GetFilteredNotes` + Use a visitor for handling -mineraddress config option + Add support for decoding and encoding Unified Addresses + Pass network type through to UA address handling logic + CI: Add workflow that runs general lints + CI: Check scripted diffs + CI: Add Rust lints + Document why a nested call to ExtractMinerAddress is not recursive + Add constants for UA typecodes + Postpone dependency updates we aren't doing in this release + depends: Update Rust to 1.54.0 + depends: Update Clang / libcxx to LLVM 12 + depends: Update utfcpp to 3.2.1 + depends: Fix issue cross-compiling BDB to Windows with Clang 12 + rust: cargo update + rust: metrics 0.17 + CI: Use Rust 1.54 for lints + cargo fmt + test: Wait for transaction propagation in shorter_block_times RPC test + test: Fix race condition in p2p_txexpiringsoon + Revert "Remove reference to -reindex-chainstate" + test: Flush wallet in WriteCryptedSaplingZkeyDirectToDb before reopening + qa: Bump `sync_mempool` timeout for `prioritisetransaction.py` + ProcessGetData(): Rework IsExpiringSoon check + test: Print reject reason if RPC test block rejected instead of accepted + test: Fix pyflakes warnings + CI: Ignore errors from general lints we don't yet have passing + lint: remove duplicate include + lint: Add missing include guards + test: Add NU5 test cases to existing RPC tests + builder: Generate v5 transactions from NU5 activation + Print `nConsensusBranchId` in `CTransaction::ToString` + Separate the consensus and internal consistency checks for branch ID + Parse consensus branch ID when reading v5 transaction format + test: Use correct field of getnetworkinfo to read protocol version + CI: Add Dependabot config to keep Actions up-to-date + Introduce a WTxId struct + Implement CInv message type MSG_WTX + test: Fix bugs in mininode transaction parser + test: Add v5 tx support to mininode + ProcessGetData: Respond to MSG_WTX requests + Add MSG_WTX support to inv messages + Use wtxid for peer state management + test: Implement CInv.__eq__() for mininode to simplify RPC test + Postpone dependency updates that require CMake + depends: Update Rust to 1.54.0 + test: Fix bug in mininode.SpendDescription.deserialize + Add named constants for legacy tx authDigest placeholder value + qa: Boost 1.77.0 + cargo update + Migrate to latest revisions of Zcash Rust crates + test: Set up mininodes at the start of feature_zip239 + net: Reject unknown CInv message types + make-release.py: Versioning changes for 4.5.0-rc1. + make-release.py: Updated manpages for 4.5.0-rc1. + +John Newbery (10): + [tests] Remove wallet accounts test + [wallet] GetBalance can take an isminefilter filter. + [wallet] Factor out GetWatchOnlyBalance() + [wallet] deduplicate GetAvailableCredit logic + [wallet] factor out GetAvailableWatchOnlyBalance() + [wallet] GetBalance can take a min_depth argument. + [RPC] [wallet] allow getbalance to use min_conf and watch_only without accounts. + [wallet] Remove wallet account RPCs + [wallet] Kill accounts + [net] split PushInventory() + +Jonas Schnelli (1): + fix locking issue with new mempool limiting + +Kris Nuttycombe (46): + Update transaction auth commitments for pre-v5 transactions. + Move OrchardBundle to its own header file. + Implement the Rust side of the incremental merkle tree FFI. + Orchard changes to coins & consensus. + Return std::optional for GetAnchor + Check nullifiers length against bundle actions length. + Add Orchard bundle commitments to merkle tree. + Add Orchard merkle tree anchor tests. + Documentation cleanup. + Update orchard dependency. + Update to released version of incrementalmerkletree + Apply suggestions from code review + Apply suggestions from code review + Fix Orchard incremental Merkle tree empty root. + Fix header guards for incremental_sinsemilla_tree.h + Apply style suggestions. + Consistently panic on null commitment tree pointers. + Fix implmentation of OrchardMerkleTree.DynamicMemoryUsage + Document source of Orchard merkle tree test data. + Apply suggestions from code review + Add consensus check for duplicate Orchard nullifiers within a single transaction. + Add Orchard nullifiers to nullifiers cache. + Apply suggestions from code review + Ensure Sapling versions are valid after NU5 + Make CTransaction::nConsensusBranchId a std::optional + Add NU5 upper bound check on nSpendsSapling, nOutputsSapling, nActionsOrchard + Check consensus branch ID for V5 transactions. + Rename tx.valueBalance -> tx.valueBalanceSapling + Make valueBalanceSapling a private non-const member of CTransaction. + Add Orchard value balance checks. + Account for Orchard balance in GetValueOut and GetShieldedValueIn. + Retract partial Orchard test support. + Add check that v5 transactions have empty Sprout joinsplits. + Prevent undefined behaviour in `CTransaction::GetValueOut()` + ZIP 213: Add checks to support Orchard shielded coinbase outputs. + Add check for consistency between nActionsOrchard and Orchard flags. + Ensure that the Orchard note commitment tree does not exceed its maximum size. + Update Orchard commitment tree hashes to use total MerkleCRH^Orchard. + Apply suggestions from code review + Make Sapling Spend and Ouput count, and Orchard Action count checks be noncontextual. + Use DOS level 100 for noncontextual checks. + Fix error strings to correctly reflect context. + Remove unused account-related wallet methods. + Use manual serialization for Merkle frontiers rather than bincode. + Fix clippy complaints. + Lock the wallet in SetBestChainINTERNAL + +Larry Ruane (1): + ZIP 225: v5 transaction check rules + +Luke Dashjr (1): + Optimisation: Store transaction list order in memory rather than compute it every need + +Marco Falke (1): + [qa] py2: Unfiddle strings into bytes explicitly + +Matt Corallo (4): + Fix calling mempool directly, instead of pool, in ATMP + Track (and define) ::minRelayTxFee in CTxMemPool + Add CFeeRate += operator + Print mempool size in KB when adding txn + +Patrick Strateman (5): + Fix insanity of CWalletDB::WriteTx and CWalletTx::WriteToDisk + Add CWallet::ListAccountCreditDebit + Add CWallet::ReorderTransactions and use in accounting_tests.cpp + Move CWalletDB::ReorderTransactions to CWallet + Move GetAccountBalance from rpcwallet.cpp into CWallet::GetAccountBalance + +Pieter Wuille (16): + Replace trickle nodes with per-node/message Poisson delays + Change mapRelay to store CTransactions + Make ProcessNewBlock dbp const and update comment + Switch reindexing to AcceptBlock in-loop and ActivateBestChain afterwards + Optimize ActivateBestChain for long chains + Add -reindex-chainstate that does not rebuild block index + Report reindexing progress in GUI + Split up and optimize transaction and block inv queues + Handle mempool requests in send loop, subject to trickle + Return mempool queries in dependency order + Add support for unique_ptr and shared_ptr to memusage + Switch CTransaction storage in mempool to std::shared_ptr + Optimize the relay map to use shared_ptr's + Optimization: don't check the mempool at all if no mempool req ever + Optimization: use usec in expiration and reuse nNow + Get rid of CTxMempool::lookup() entirely + +Russell Yanofsky (2): + [wallet] Add GetLegacyBalance method to simplify getbalance RPC + [wallet] Remove unneeded legacy getbalance code + +Shaul Kfir (1): + Add absurdly high fee message to validation state (for RPC propagation) + +Suhas Daftuar (3): + Use txid as key in mapAlreadyAskedFor + Reverse the sort on the mempool's feerate index + Only use AddInventoryKnown for transactions + +Technetium (1): + add missing aarch64 build deps + +Wladimir J. van der Laan (17): + streams: Add data() method to CDataStream + streams: Remove special cases for ancient MSVC + dbwrapper: Use new .data() method of CDataStream + wallet: Use CDataStream.data() + net: Consistent checksum handling + net: Hardcode protocol sizes and use fixed-size types + protocol.h: Move MESSAGE_START_SIZE into CMessageHeader + protocol.h: Make enums in GetDataMsg concrete values + Add assertion and cast before sending reject code + Add debug message to CValidationState for optional extra information + Introduce REJECT_INTERNAL codes for local AcceptToMempool errors + Add function to convert CValidationState to a human-readable message + Remove most logging from transaction validation + Add information to errors in ConnectBlock, CheckBlock + Move mempool rejections to new debug category + net: Fix sent reject messages for blocks and transactions + test: Add basic test for `reject` code + +hexabot (2): + Update depends/packages/native_clang.mk + Update depends/packages/native_rust.mk + +Marshall Gaucher (5): + Remove sprout funding flow logic + Add fix and note for timing issue + Update funding logic bug + Add usage documentation for manual and faucet driven tests + Update funding logic + +Jack Grigg (12): + Document next_pow2 effects and algorithm source + Improvements to CBlock::BuildAuthDataMerkleTree + rust: Explicitly return null hash for pre-v5 auth digests + book: Note that cargo patches work with absolute paths + Improve docs about setting CBlockIndex hash fields + test: Cleanups to ZIP 221 Python test code + Minor fixes to documentation and formatting + Fix typo in method documentation + Track lengths when copying receiver data from C++ to Rust + depends: Greatly simplify the Clang 12 patch + Adjust code comments to remove topological-sort references + Fix typos + diff --git a/doc/release-notes/release-notes-4.5.0.md b/doc/release-notes/release-notes-4.5.0.md new file mode 100644 index 00000000000..94453bd741e --- /dev/null +++ b/doc/release-notes/release-notes-4.5.0.md @@ -0,0 +1,387 @@ +Notable changes +=============== + +Network Upgrade 5 +----------------- + +The code preparations for the Network Upgrade 5 consensus rules are finished and +included in this release. The following ZIPs are being deployed: + +- [ZIP 216: Require Canonical Jubjub Point Encodings](https://zips.z.cash/zip-0216) +- [ZIP 224: Orchard Shielded Protocol](https://zips.z.cash/zip-0224) +- [ZIP 225: Version 5 Transaction Format](https://zips.z.cash/zip-0225) +- [ZIP 239: Relay of Version 5 Transactions](https://zips.z.cash/zip-0239) +- [ZIP 244: Transaction Identifier Non-Malleability](https://zips.z.cash/zip-0244) + +NU5 will activate on testnet at height **1,590,000**, and can also be activated +at a specific height in regtest mode by setting the config option +`-nuparams=f919a198:HEIGHT`. + +The testnet activation of NU5, and `zcashd` v4.5.0 itself, is aimed at enabling +existing Zcash users to test their software and make the necessary changes to be +compatible with the new consensus rules. In particular: + +- Wallets should start adding support for v5 transactions. +- Miners and mining pools should ensure that their software is compatible with + the semantic change to the block header specified in + [ZIP 244](https://zips.z.cash/zip-0244#block-header-changes) + +A subsequent v4.5.1 release in the coming weeks will add support for generating +and using Unified Addresses ([ZIP 316](https://zips.z.cash/zip-0316)), which +will enable `zcashd` wallets to interact with the Orchard shielded pool. + +As with previous network upgrades, it is possible that backwards-incompatible +changes might be made to the consensus rules in this testing phase, prior to +setting the mainnet activation height. In the event that this happens, testnet +will be rolled back in v5.0.0 and a second testnet activation will occur. + +See [ZIP 252](https://zips.z.cash/zip-0252) for additional information about the +deployment process for NU5. + +Rejecting unknown `CInv` message types +-------------------------------------- + +Previously, if `zcashd` received an `inv` or `getdata` message containing +unknown `CInv` message types, it would ignore them and process the remainder of +the message. Starting with v4.5.0, `zcashd` will instead drop the entire `inv` +or `getdata` message and reply with a `reject` message. This will enable node +operators to discover whether their nodes are sending unexpected `CInv` types; +in particular, node operators should ensure their software does not produce the +`MSG_WTX` CInv message type intended for the Bitcoin network, which is +incompatible with the `MSG_WTX` CInv message type defined in ZIP 239 (which will +be used from NU5 activation for advertising v5 transactions). + +Deprecated or removed RPCs +-------------------------- + +- The 'account' API inherited from Bitcoin Core has been disabled since the + launch of Zcash. Following its deprecation in Bitcoin Core v0.17 and removal + in Bitcoin Core v0.18, we have now removed the API from `zcashd`. + + +Changelog +========= + +Aditya Kulkarni (1): + Sort taddr txns by txindex in addition to height + +Alex Morcos (4): + Store the total sig op count of a tx. + Add a score index to the mempool. + Add TxPriority class and comparator + tidy up CInv::GetCommand + +Daira Hopwood (8): + Improve error message when a block would overfill the Orchard commitment tree. + More precise terminology: "lock free" -> "unlocked" + ZIP 339 support. + Update URL for Boost source download (from dl.bintray.com to boostorg.jfrog.io). + Cargo.toml: use librustzcash after the merge of https://github.com/zcash/librustzcash/pull/424 . + Update unified address test data to take account of HRPs in padding (https://github.com/zcash/librustzcash/pull/419). + Avoid need to cast away const in the C caller of zip339_free_phrase. + Update authors of librustzcash to everyone currently and formerly on Core team (in alphabetical order). + +Eric Lombrozo (2): + Removed ppszTypeName from protocol.cpp + getdata enum issue fix + +Ethan Heilman (1): + Fix typo adddrman to addrman as requested in #8070 + +Ethan Heilman (1): + Remove non-determinism which is breaking net_tests #8069 + +Gregory Maxwell (4): + Eliminate TX trickle bypass, sort TX invs for privacy and priority. + Move bloom and feerate filtering to just prior to tx sending. + Do not use mempool for GETDATA for tx accepted after the last mempool req. + Defer inserting into maprelay until just before relaying. + +Jack Grigg (124): + Re-include reading blocks from disk in block connection benchmark + cargo update + Migrate to latest zcash_* crates + metrics 0.16 and metrics-exporter-prometheus 0.5 + Implement ZIP 216 consensus rules + Extract SpendDescriptionV5 and OutputDescriptionV5 classes + rust: Enable C++ streams to be passed into Rust code + ZIP 225 tx format constants + v5 transaction format parser + contrib: Add BOSL to contrib/debian/copyright + Remove early return logic from transaction parsing + rust: Document read_callback_t and write_callback_t + CTransaction: Make new ZIP 225 fields non-const and private + ZIP 244 transaction digests + ZIP 244 signature digests + ZIP 244 hashAuthDataRoot computation + Fix tests that assume CTxOuts can be "null" + test: Generate valid Sapling types + test: Small fixes to sighash test vector generation + test: Regenerate sighash.json after generator fixes + Throw an exception instead of asserting if Rust tx parser fails + CI: Publish correct book directory + CI: Build book with latest mdbook + rust: Documentation improvements to FFI methods + Implement Orchard authorization batch validator + Implement Orchard signature validation consensus rules + rust: Fix patched dependencies + book: Add dev guide page about Rust dependencies + Rename hashLightClientRoot to hashBlockCommitments in block header + ZIP 244 hashBlockCommitments implementation + test: Check for valid hashBlockCommitments construction post-NU5 + Skip hashBlockCommitments check when testing block templates + test: Check hashBlockCommitments before, at, and after NU5 activation + ConnectBlock: Check NU activation when deriving block commitments + Copy authDigest in CTransaction::operator=(const CTransaction &tx) + rust: Move history tree FFI logic into a module + rust: Migrate to zcash_history with versioned trees + rust: Move history tree FFI declarations into a separate header + test: Use valid consensus branch IDs in history tree tests + Use V2 history trees from NU5 onward + test: Check history trees across Canopy and NU5 activations + rpc: Document getblock RPC finalorchardroot field, omit before NU5 + rust: Document some requirements for history tree FFI methods + test: Add test case for popping from an empty history tree + Implement Orchard pool value tracking + rust: Load Orchard circuit parameters at startup + Check Orchard bundle-specific consensus rules, i.e. proofs + test: Update CCoinsViewTest with changes to CCoinsView interface + Include Orchard bundle in transaction dynamic usage + ZIP 203: Enforce coinbase nExpiryHeight consensus rule from NU5 + test: Check for updated empty-tx reject messages in transaction tests + test: Fix OverwinterExpiryHeight test after ZIP 203 contextual changes + miner: Set coinbase expiry height to block height from NU5 activation + Introduce libzcash::RawAddress type + Use `libzcash::RawAddress` in `CWallet::GetFilteredNotes` + Use a visitor for handling -mineraddress config option + Add support for decoding and encoding Unified Addresses + Pass network type through to UA address handling logic + CI: Add workflow that runs general lints + CI: Check scripted diffs + CI: Add Rust lints + Document why a nested call to ExtractMinerAddress is not recursive + Add constants for UA typecodes + Postpone dependency updates we aren't doing in this release + depends: Update Rust to 1.54.0 + depends: Update Clang / libcxx to LLVM 12 + depends: Update utfcpp to 3.2.1 + depends: Fix issue cross-compiling BDB to Windows with Clang 12 + rust: cargo update + rust: metrics 0.17 + CI: Use Rust 1.54 for lints + cargo fmt + test: Wait for transaction propagation in shorter_block_times RPC test + test: Fix race condition in p2p_txexpiringsoon + Revert "Remove reference to -reindex-chainstate" + test: Flush wallet in WriteCryptedSaplingZkeyDirectToDb before reopening + qa: Bump `sync_mempool` timeout for `prioritisetransaction.py` + ProcessGetData(): Rework IsExpiringSoon check + test: Print reject reason if RPC test block rejected instead of accepted + test: Fix pyflakes warnings + CI: Ignore errors from general lints we don't yet have passing + lint: remove duplicate include + lint: Add missing include guards + test: Add NU5 test cases to existing RPC tests + builder: Generate v5 transactions from NU5 activation + Print `nConsensusBranchId` in `CTransaction::ToString` + Separate the consensus and internal consistency checks for branch ID + Parse consensus branch ID when reading v5 transaction format + test: Use correct field of getnetworkinfo to read protocol version + CI: Add Dependabot config to keep Actions up-to-date + Introduce a WTxId struct + Implement CInv message type MSG_WTX + test: Fix bugs in mininode transaction parser + test: Add v5 tx support to mininode + ProcessGetData: Respond to MSG_WTX requests + Add MSG_WTX support to inv messages + Use wtxid for peer state management + test: Implement CInv.__eq__() for mininode to simplify RPC test + Postpone dependency updates that require CMake + depends: Update Rust to 1.54.0 + test: Fix bug in mininode.SpendDescription.deserialize + Add named constants for legacy tx authDigest placeholder value + qa: Boost 1.77.0 + cargo update + Migrate to latest revisions of Zcash Rust crates + test: Set up mininodes at the start of feature_zip239 + net: Reject unknown CInv message types + make-release.py: Versioning changes for 4.5.0-rc1. + make-release.py: Updated manpages for 4.5.0-rc1. + make-release.py: Updated release notes and changelog for 4.5.0-rc1. + Migrate to latest revisions of orchard and the zcash_* crates + contrib: Add script for generating a graph of our Rust dependencies + cargo update + build: Add primitives/orchard.h to list of header files + build: Ensure that cargo uses vendored dependencies for git repos + build: Add missing source file to zcash_gtest_SOURCES + rust: Move Orchard batch logic into BatchValidator methods + wallet: Batch-validate all Orchard signatures in the wallet on load + rust: Skip running the Orchard batch validator on an empty batch + bench: Add Orchard logic to zcbenchmarks + cargo update + Update halo2 and orchard dependencies with BOSL Zcash exception + make-release.py: Versioning changes for 4.5.0. + make-release.py: Updated manpages for 4.5.0. + +John Newbery (10): + [tests] Remove wallet accounts test + [wallet] GetBalance can take an isminefilter filter. + [wallet] Factor out GetWatchOnlyBalance() + [wallet] deduplicate GetAvailableCredit logic + [wallet] factor out GetAvailableWatchOnlyBalance() + [wallet] GetBalance can take a min_depth argument. + [RPC] [wallet] allow getbalance to use min_conf and watch_only without accounts. + [wallet] Remove wallet account RPCs + [wallet] Kill accounts + [net] split PushInventory() + +Jonas Schnelli (1): + fix locking issue with new mempool limiting + +Kris Nuttycombe (46): + Update transaction auth commitments for pre-v5 transactions. + Move OrchardBundle to its own header file. + Implement the Rust side of the incremental merkle tree FFI. + Orchard changes to coins & consensus. + Return std::optional for GetAnchor + Check nullifiers length against bundle actions length. + Add Orchard bundle commitments to merkle tree. + Add Orchard merkle tree anchor tests. + Documentation cleanup. + Update orchard dependency. + Update to released version of incrementalmerkletree + Apply suggestions from code review + Apply suggestions from code review + Fix Orchard incremental Merkle tree empty root. + Fix header guards for incremental_sinsemilla_tree.h + Apply style suggestions. + Consistently panic on null commitment tree pointers. + Fix implmentation of OrchardMerkleTree.DynamicMemoryUsage + Document source of Orchard merkle tree test data. + Apply suggestions from code review + Add consensus check for duplicate Orchard nullifiers within a single transaction. + Add Orchard nullifiers to nullifiers cache. + Apply suggestions from code review + Ensure Sapling versions are valid after NU5 + Make CTransaction::nConsensusBranchId a std::optional + Add NU5 upper bound check on nSpendsSapling, nOutputsSapling, nActionsOrchard + Check consensus branch ID for V5 transactions. + Rename tx.valueBalance -> tx.valueBalanceSapling + Make valueBalanceSapling a private non-const member of CTransaction. + Add Orchard value balance checks. + Account for Orchard balance in GetValueOut and GetShieldedValueIn. + Retract partial Orchard test support. + Add check that v5 transactions have empty Sprout joinsplits. + Prevent undefined behaviour in `CTransaction::GetValueOut()` + ZIP 213: Add checks to support Orchard shielded coinbase outputs. + Add check for consistency between nActionsOrchard and Orchard flags. + Ensure that the Orchard note commitment tree does not exceed its maximum size. + Update Orchard commitment tree hashes to use total MerkleCRH^Orchard. + Apply suggestions from code review + Make Sapling Spend and Ouput count, and Orchard Action count checks be noncontextual. + Use DOS level 100 for noncontextual checks. + Fix error strings to correctly reflect context. + Remove unused account-related wallet methods. + Use manual serialization for Merkle frontiers rather than bincode. + Fix clippy complaints. + Lock the wallet in SetBestChainINTERNAL + +Larry Ruane (1): + ZIP 225: v5 transaction check rules + +Luke Dashjr (1): + Optimisation: Store transaction list order in memory rather than compute it every need + +Marco Falke (1): + [qa] py2: Unfiddle strings into bytes explicitly + +Matt Corallo (4): + Fix calling mempool directly, instead of pool, in ATMP + Track (and define) ::minRelayTxFee in CTxMemPool + Add CFeeRate += operator + Print mempool size in KB when adding txn + +Patrick Strateman (5): + Fix insanity of CWalletDB::WriteTx and CWalletTx::WriteToDisk + Add CWallet::ListAccountCreditDebit + Add CWallet::ReorderTransactions and use in accounting_tests.cpp + Move CWalletDB::ReorderTransactions to CWallet + Move GetAccountBalance from rpcwallet.cpp into CWallet::GetAccountBalance + +Pieter Wuille (16): + Replace trickle nodes with per-node/message Poisson delays + Change mapRelay to store CTransactions + Make ProcessNewBlock dbp const and update comment + Switch reindexing to AcceptBlock in-loop and ActivateBestChain afterwards + Optimize ActivateBestChain for long chains + Add -reindex-chainstate that does not rebuild block index + Report reindexing progress in GUI + Split up and optimize transaction and block inv queues + Handle mempool requests in send loop, subject to trickle + Return mempool queries in dependency order + Add support for unique_ptr and shared_ptr to memusage + Switch CTransaction storage in mempool to std::shared_ptr + Optimize the relay map to use shared_ptr's + Optimization: don't check the mempool at all if no mempool req ever + Optimization: use usec in expiration and reuse nNow + Get rid of CTxMempool::lookup() entirely + +Russell Yanofsky (2): + [wallet] Add GetLegacyBalance method to simplify getbalance RPC + [wallet] Remove unneeded legacy getbalance code + +Shaul Kfir (1): + Add absurdly high fee message to validation state (for RPC propagation) + +Suhas Daftuar (3): + Use txid as key in mapAlreadyAskedFor + Reverse the sort on the mempool's feerate index + Only use AddInventoryKnown for transactions + +Technetium (1): + add missing aarch64 build deps + +Wladimir J. van der Laan (17): + streams: Add data() method to CDataStream + streams: Remove special cases for ancient MSVC + dbwrapper: Use new .data() method of CDataStream + wallet: Use CDataStream.data() + net: Consistent checksum handling + net: Hardcode protocol sizes and use fixed-size types + protocol.h: Move MESSAGE_START_SIZE into CMessageHeader + protocol.h: Make enums in GetDataMsg concrete values + Add assertion and cast before sending reject code + Add debug message to CValidationState for optional extra information + Introduce REJECT_INTERNAL codes for local AcceptToMempool errors + Add function to convert CValidationState to a human-readable message + Remove most logging from transaction validation + Add information to errors in ConnectBlock, CheckBlock + Move mempool rejections to new debug category + net: Fix sent reject messages for blocks and transactions + test: Add basic test for `reject` code + +hexabot (2): + Update depends/packages/native_clang.mk + Update depends/packages/native_rust.mk + +Marshall Gaucher (5): + Remove sprout funding flow logic + Add fix and note for timing issue + Update funding logic bug + Add usage documentation for manual and faucet driven tests + Update funding logic + +Jack Grigg (12): + Document next_pow2 effects and algorithm source + Improvements to CBlock::BuildAuthDataMerkleTree + rust: Explicitly return null hash for pre-v5 auth digests + book: Note that cargo patches work with absolute paths + Improve docs about setting CBlockIndex hash fields + test: Cleanups to ZIP 221 Python test code + Minor fixes to documentation and formatting + Fix typo in method documentation + Track lengths when copying receiver data from C++ to Rust + depends: Greatly simplify the Clang 12 patch + Adjust code comments to remove topological-sort references + Fix typos + diff --git a/doc/release-notes/release-notes-4.5.1-1.md b/doc/release-notes/release-notes-4.5.1-1.md new file mode 100644 index 00000000000..f7847c3bcdd --- /dev/null +++ b/doc/release-notes/release-notes-4.5.1-1.md @@ -0,0 +1,46 @@ +Notable changes +=============== + +Added v5 transactions to standard rules +--------------------------------------- + +In v4.5.0 we added the v5 transaction format to the NU5 consensus rules for +testnet. However, it was omitted from the standard rules, which meant that +`zcashd` testnet nodes would not accept v5 transactions into their mempools, +causing them to not be propagated or mined. This release updates the `zcashd` +standard rules to accept v5 transactions alongside v4 transactions. + +New `listaddresses` RPC method +------------------------------ + +The `listaddresses` endpoint has been added to the RPC API. This method +allows the caller to obtain addresses managed by the wallet, grouped +by the source of the address, including both those addresses generated +by the wallet and those associated with imported viewing or spending +keys. This provides functionality that replaces and subsumes the +previously-removed `getaddressesbyaccount` method. + +Changelog +========= + +Jack Grigg (6): + Mark v5 transaction format as standard for NU5 + Fix comment + cargo update + depends: Postpone dependency updates + make-release.py: Versioning changes for 4.5.1-1. + make-release.py: Updated manpages for 4.5.1-1. + +Kris Nuttycombe (11): + Add `listaddresses` RPC method. + Categorize listaddresses result by source type. + Correctly handle imported Sapling addresses + Apply suggestions from code review + Apply suggestions from code review + Group legacy_hdseed Sapling addresses by account ID. + Update release notes for v4.5.1-1 to reflect the addition of `listaddresses` + Include `ImportedWatchOnly` as a PaymentAddressSource result. + Add listaddresses check to wallet_addresses.py + Consistently group Sapling addresses by IVK for every source. + Use lowerCamelCase for listaddresses JSON + diff --git a/doc/release-notes/release-notes-4.5.1.md b/doc/release-notes/release-notes-4.5.1.md new file mode 100644 index 00000000000..c0229a5e75b --- /dev/null +++ b/doc/release-notes/release-notes-4.5.1.md @@ -0,0 +1,80 @@ +Notable changes +=============== + +Fixed bugs in the testnet Orchard circuit +----------------------------------------- + +In the `zcashd v4.5.0` release notes we indicated that a testnet rollback might +occur to update the consensus rules, if we needed to make backwards-incompatible +changes. Shortly after `zcashd v4.5.0` was released, during another internal +review of the Orchard circuit, we identified two bugs that would affect the +upcoming testnet activation of NU5: + +- The diversifier base `g_d_old`, for the note being spent, is required to be a + non-identity point. A note created from a payment address with `g_d` set to + the identity (via collaboration between sender and recipient) could be spent + multiple times with different nullifiers (corresponding to different `ivk`s). + The code outside the circuit correctly enforced the non-identity requirement, + but the circuit did not correctly constrain this, and allowed the prover to + witness the identity. + +- SinsemillaCommit can be modeled as a Pedersen commitment to an output of + SinsemillaHash: `SinsemillaCommit(r, M) = SinsemillaHashToPoint(M) + [r] R`. + The specification used incomplete addition here, matching its use inside + SinsemillaHash. However, unlike in SinsemillaHash, an exceptional case can be + produced here when `r = 0`. The derivations of `rivk` (for computing `ivk`) + and `rcm` (for computing the note commitment) normally ensure that `r = 0` + can only occur with negligible probability, but these derivations are not + checked by the circuit for efficiency; thus SinsemillaCommit needs to use + complete addition. + +These bugs do not affect mainnet, as `zcashd v4.5.0` only set the activation +height for NU5 on testnet for testing purposes. Nevertheless, in the interest of +keeping the testnet environment as close to mainnet as possible, we are fixing +these bugs immediately. This means a change to the NU5 consensus rules, and a +new testnet activation height for NU5. + +To this end, the following changes are made in `zcashd v4.5.1`: + +- The consensus branch ID for NU5 is changed to `0x37519621`. +- The protocol version indicating NU5-aware testnet nodes is set to `170015`. +- The testnet activation height for NU5 is set to **1,599,200**. + +Testnet nodes that upgrade to `zcashd v4.5.1` prior to block height 1,590,000 +will follow the new testnet network upgrade. Testnet nodes that are running +`zcashd v4.5.0` at that height will need to upgrade to `v4.5.1` and then run +with `-reindex`. + +As always, it is possible that further backwards-incompatible changes might be +made to the NU5 consensus rules in this testing phase, prior to setting the +mainnet activation height, as we continue to conduct additional internal review. +In the event that this happens, testnet will be rolled back in (or prior to) +v5.0.0, and a new testnet activation will occur. + +Fixed regression in `getbalance` RPC method +------------------------------------------- + +`zcashd v4.5.0` removed the account API from the wallet, following its +deprecation and removal in upstream Bitcoin Core. As part of the upstream +changes, the `getbalance` RPC method was altered from using two custom balance +computation methods, to instead relying on `CWallet::GetBalance`. This method +internally relies on `CWalletTx::IsFromMe` as part of identifying "trusted" +zero-confirmation transactions to include in the balance calculation. + +There is an equivalent and closely-named `CWallet::IsFromMe` method, which is +used throughout the wallet, and had been updated before Zcash launched to be +aware of spent shielded notes. The change to `getbalance` exposed a bug: +`CWalletTx::IsFromMe` had not been similarly updated, which caused `getbalance` +to ignore wallet-internal (sent between two addresses in the node's wallet) +unshielding transactions with zero confirmations. This release fixes the bug. + +Changelog +========= + +Jack Grigg (5): + wallet: Check spent shielded notes in CWalletTx::IsFromMe + Fix bugs in testnet Orchard circuit + depends: Postpone native_ccache 4.4.2 + make-release.py: Versioning changes for 4.5.1. + make-release.py: Updated manpages for 4.5.1. + diff --git a/doc/release-notes/release-notes-4.6.0-1.md b/doc/release-notes/release-notes-4.6.0-1.md new file mode 100644 index 00000000000..975376aa164 --- /dev/null +++ b/doc/release-notes/release-notes-4.6.0-1.md @@ -0,0 +1,37 @@ +`getblocktemplate` regression fix +================================= + +We added support for the NU5 consensus rules in v4.5.0, which alters the +block header to contain a `hashBlockCommitments` value instead of the +chain history root. However, the output of `getblocktemplate` wasn't +returning this value; once NU5 activated, the `blockcommitmentshash` +field was being set to "null" (all-zeroes). + +In v4.6.0 we added full NU5 support to `getblocktemplate`, by adding a +`defaultroots` field that gave default values for `hashBlockCommitments` +and the components required to derive it. However, in doing so we +introduced a regression in the (now-deprecated) legacy fields, where +prior to NU5 activation they contained nonsense. + +This release fixes the output of `getblocktemplate` to have the intended +semantics for all fields: + +- The `blockcommitmentshash` and `authdataroot` fields in `defaultroots` + are now omitted from block templates for heights before NU5 activation. + +- The legacy fields now always contain the default value to be placed + into the block header (regaining their previous semantics). + +Changelog +========= + +Jack Grigg (3): + rpc: Fix regression in getblocktemplate output + make-release.py: Versioning changes for 4.6.0-1. + make-release.py: Updated manpages for 4.6.0-1. + +Larry Ruane (3): + assert that the return value of submitblock is None + test: check getblocktemplate output before and after NU5 + test: Fix ZIP 244 implementation + diff --git a/doc/release-notes/release-notes-4.6.0-rc1.md b/doc/release-notes/release-notes-4.6.0-rc1.md new file mode 100644 index 00000000000..1bfd543d0f1 --- /dev/null +++ b/doc/release-notes/release-notes-4.6.0-rc1.md @@ -0,0 +1,111 @@ +Notable changes +=============== + +Wallet +------ + +From this release, newly-created wallets will save the chain name ("Zcash") and +network identifier (e.g. "main") to the `wallet.dat` file. This will enable the +`zcashd` node to check on subsequent starts that the `wallet.dat` file matches +the node's configuration. Existing wallets will start saving this information in +a later release. + +`libzcash_script` +----------------- + +Two new APIs have been added to this library (`zcash_script_legacy_sigop_count` +and `zcash_script_legacy_sigop_count_precomputed`), for counting the number of +signature operations in the transparent inputs and outputs of a transaction. +The presence of these APIs is indicated by a library API version of 2. + +Updated RPCs +------------ + +- Fixed an issue where `ERROR: spent index not enabled` would be logged + unnecessarily on nodes that have either insightexplorer or lightwalletd + configuration options enabled. + +- The `getmininginfo` RPC now omits `currentblockize` and `currentblocktx` + when a block was never assembled via RPC on this node during its current + process instantiation. (#5404) + +Changelog +========= + +Alex Wied (1): + Update support for FreeBSD + +Charlie O'Keefe (1): + Add buster to the list of suites used by gitian + +Dimitris Apostolou (1): + Fix typos + +Jack Grigg (22): + contrib: Update Debian copyright file to follow the v1 format + contrib: Add license information for libc++ and libevent + cargo update + tracing-subscriber 0.3 + Bump all postponed dependencies + depends: Update Rust to 1.56.1 + depends: Update Clang / libcxx to LLVM 13 + rust: Move `incremental_sinsemilla_tree_ffi` into crate root + CI: Add Pyflakes to lints workflow + cargo update + ed25519-zebra 3 + cargo update + cargo update + depends: Update Boost to 1.78.0 + depends Update Rust to 1.57.0 + qa: Postpone recent CCache releases + Revert "lint: Fix false positive" + rust: Remove misleading log message + Migrate to latest revisions of Zcash Rust crates + Update release notes + make-release.py: Versioning changes for 4.6.0-rc1. + make-release.py: Updated manpages for 4.6.0-rc1. + +Janito Vaqueiro Ferreira Filho (1): + Move `CurrentTxVersionInfo` into a new file + +Kris Nuttycombe (7): + Add BIP 44 coin type to persisted wallet state. + Persist network id string instead of bip44 coin type. + Add a check to test that wallet load fails if we're on the wrong network. + Remove unused `AddDestData` method. + Fix wallet-related wording in doc/reduce-traffic.md + Rename OrchardMerkleTree -> OrchardMerkleFrontier + Batch-verify Orchard transactions at the block level. + +Larry Ruane (6): + add TestSetIBD(bool) for testing + Disable IBD for all boost tests + better wallet network info error handling + test: automatically add missing nuparams + Don't log 'ERROR: spent index not enabled' + getblocktemplate: add NU5 commitments to new `defaultroots` section + +Marco Falke (1): + [rpc] mining: Omit uninitialized currentblockweight, currentblocktx + +Marshall Gaucher (1): + Update entrypoint.sh + +Sasha (1): + fix typo in docker run's volume argument + +sgmoore (1): + Update reduce-traffic.md - add one word + +Jack Grigg (1): + contrib: Add space between URL and period + +teor (7): + Add sigop count functions to zcash_script library + Increment the zcash_script API version + Remove an unused header + Use correct copyright header + Remove redundant variable + Explain UINT_MAX error return value + Explain how to get rid of a tiny duplicated function + diff --git a/doc/release-notes/release-notes-4.6.0.md b/doc/release-notes/release-notes-4.6.0.md new file mode 100644 index 00000000000..26e1f36527b --- /dev/null +++ b/doc/release-notes/release-notes-4.6.0.md @@ -0,0 +1,126 @@ +Notable changes +=============== + +Wallet +------ + +From this release, newly-created wallets will save the chain name ("Zcash") and +network identifier (e.g. "main") to the `wallet.dat` file. This will enable the +`zcashd` node to check on subsequent starts that the `wallet.dat` file matches +the node's configuration. Existing wallets will start saving this information in +a later release. + +`libzcash_script` +----------------- + +Two new APIs have been added to this library (`zcash_script_legacy_sigop_count` +and `zcash_script_legacy_sigop_count_precomputed`), for counting the number of +signature operations in the transparent inputs and outputs of a transaction. +The presence of these APIs is indicated by a library API version of 2. + +Updated RPCs +------------ + +- The `getblocktemplate` RPC method output now includes a `defaultroots` field, + which provides various tree roots and block commitments matching the contents + of the block template. If any part of the block template marked as `mutable` + in the RPC method output is mutated, these roots may need to be recomputed. + For more information on the derivation process, see the block header changes + in [ZIP 244](https://zips.z.cash/zip-0244#block-header-changes). + +- Fixed an issue where `ERROR: spent index not enabled` would be logged + unnecessarily on nodes that have either `-insightexplorer` or `-lightwalletd` + configuration options enabled. + +- The `getmininginfo` RPC now omits `currentblocksize` and `currentblocktx` + when a block was never assembled via RPC on this node during its current + process instantiation. (#5404) + +Changelog +========= + +Alex Wied (1): + Update support for FreeBSD + +Charlie O'Keefe (2): + Add buster to the list of suites used by gitian + Add libtinfo5 to gitian packages list + +Dimitris Apostolou (1): + Fix typos + +Jack Grigg (23): + contrib: Update Debian copyright file to follow the v1 format + contrib: Add license information for libc++ and libevent + cargo update + tracing-subscriber 0.3 + Bump all postponed dependencies + depends: Update Rust to 1.56.1 + depends: Update Clang / libcxx to LLVM 13 + rust: Move `incremental_sinsemilla_tree_ffi` into crate root + CI: Add Pyflakes to lints workflow + cargo update + ed25519-zebra 3 + cargo update + cargo update + depends: Update Boost to 1.78.0 + depends Update Rust to 1.57.0 + qa: Postpone recent CCache releases + Revert "lint: Fix false positive" + rust: Remove misleading log message + Migrate to latest revisions of Zcash Rust crates + Update release notes + make-release.py: Versioning changes for 4.6.0-rc1. + make-release.py: Updated manpages for 4.6.0-rc1. + make-release.py: Updated release notes and changelog for 4.6.0-rc1. + +Janito Vaqueiro Ferreira Filho (1): + Move `CurrentTxVersionInfo` into a new file + +Kris Nuttycombe (7): + Add BIP 44 coin type to persisted wallet state. + Persist network id string instead of bip44 coin type. + Add a check to test that wallet load fails if we're on the wrong network. + Remove unused `AddDestData` method. + Fix wallet-related wording in doc/reduce-traffic.md + Rename OrchardMerkleTree -> OrchardMerkleFrontier + Batch-verify Orchard transactions at the block level. + +Larry Ruane (8): + add TestSetIBD(bool) for testing + Disable IBD for all boost tests + better wallet network info error handling + test: automatically add missing nuparams + Don't log 'ERROR: spent index not enabled' + getblocktemplate: add NU5 commitments to new `defaultroots` section + test: fix bugs in test framework + test: Use result of getblocktemplate to submitblock + +Marco Falke (1): + [rpc] mining: Omit uninitialized currentblockweight, currentblocktx + +Marshall Gaucher (1): + Update entrypoint.sh + +Sasha (5): + fix typo in docker run's volume argument + update hash for librustzcash + only librustzcash in config.offline + make-release.py: Versioning changes for 4.6.0. + make-release.py: Updated manpages for 4.6.0. + +sgmoore (1): + Update reduce-traffic.md - add one word + +Jack Grigg (1): + contrib: Add space between URL and period + +teor (7): + Add sigop count functions to zcash_script library + Increment the zcash_script API version + Remove an unused header + Use correct copyright header + Remove redundant variable + Explain UINT_MAX error return value + Explain how to get rid of a tiny duplicated function + diff --git a/doc/release-process.md b/doc/release-process.md index cb22989ba37..ebd28446bc6 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -32,7 +32,7 @@ Check that dependencies are up-to-date or have been postponed: $ ./qa/zcash/updatecheck.py ``` -If you are missing the `.updatecheck-token` file requried to run this script, +If you are missing the `.updatecheck-token` file required to run this script, please ask Taylor or another Zcash developer for a copy, or create an unprivileged personal access token for a github account and save it to the file in the format `username:hex-token`. diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 159c81620fc..66c5c75cd07 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -46,6 +46,8 @@ 'zcjoinsplit.py', 'mergetoaddress_mixednotes.py', 'wallet_shieldcoinbase_sapling.py', + 'wallet_shieldcoinbase_ua_sapling.py', + 'wallet_shieldcoinbase_ua_nu5.py', 'turnstile.py', 'walletbackup.py', 'zkey_import_export.py', @@ -58,17 +60,20 @@ 'wallet_persistence.py', 'wallet_listnotes.py', # vv Tests less than 60s vv + 'orchard_reorg.py', 'fundrawtransaction.py', 'reorg_limit.py', 'mempool_limit.py', 'p2p-fullblocktest.py', - 'paymentdisclosure.py', # vv Tests less than 30s vv 'wallet_1941.py', + 'wallet_accounts.py', 'wallet_addresses.py', 'wallet_anchorfork.py', 'wallet_changeindicator.py', 'wallet_import_export.py', + 'wallet_isfromme.py', + 'wallet_orchard.py', 'wallet_nullifiers.py', 'wallet_sapling.py', 'wallet_sendmany_any_taddr.py', @@ -102,6 +107,7 @@ 'disablewallet.py', 'keypool.py', 'getblocktemplate.py', + 'getmininginfo.py', 'bip65-cltv-p2p.py', 'bipdersig-p2p.py', 'invalidblockrequest.py', @@ -121,6 +127,7 @@ 'feature_zip239.py', 'feature_zip244_blockcommitments.py', 'upgrade_golden.py', + 'nuparams.py', 'post_heartwood_rollback.py', 'feature_logging.py', 'feature_walletfile.py', diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index d1cebbd7923..2fb02ab3cea 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -23,10 +23,6 @@ class BIP65Test(ComparisonTestFramework): - def __init__(self): - super().__init__() - self.num_nodes = 1 - def setup_network(self): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1']], diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 6f48a5e8e93..e61813c8c10 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -23,10 +23,6 @@ ''' class BIP66Test(ComparisonTestFramework): - def __init__(self): - super().__init__() - self.num_nodes = 1 - def setup_network(self): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1']], diff --git a/qa/rpc-tests/feature_zip239.py b/qa/rpc-tests/feature_zip239.py index 62fbc14f11e..19ec1550fcd 100755 --- a/qa/rpc-tests/feature_zip239.py +++ b/qa/rpc-tests/feature_zip239.py @@ -11,6 +11,7 @@ mininode_lock, msg_getdata, msg_mempool, + msg_reject, uint256_from_str, ) from test_framework.test_framework import BitcoinTestFramework @@ -26,23 +27,37 @@ hex_str_to_bytes, nuparams, p2p_port, - start_nodes, + start_node, wait_and_assert_operationid_status, ) from tx_expiry_helper import TestNode +import tempfile import time # Test ZIP 239 behaviour before and after NU5. class Zip239Test(BitcoinTestFramework): def setup_nodes(self): - return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ + extra_args=[ # Enable Canopy at height 205 to allow shielding Sprout funds first. nuparams(BLOSSOM_BRANCH_ID, 205), nuparams(HEARTWOOD_BRANCH_ID, 205), nuparams(CANOPY_BRANCH_ID, 205), nuparams(NU5_BRANCH_ID, 210), - ]] * self.num_nodes) + ] + + # We log the stderr of node 0, which the test nodes connect to. This + # enables us to check that we see the expected error logged, and also + # ensures that the test itself passes (as otherwise the stderr output + # would be interpreted as an error from the test itself). + self.log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) + + nodes = [] + nodes.append(start_node(0, self.options.tmpdir, extra_args, stderr=self.log_stderr)) + nodes.append(start_node(1, self.options.tmpdir, extra_args)) + nodes.append(start_node(2, self.options.tmpdir, extra_args)) + nodes.append(start_node(3, self.options.tmpdir, extra_args)) + return nodes def cinv_for(self, txid, authDigest=None): if authDigest is not None: @@ -104,6 +119,32 @@ def verify_last_notfound(self, testnode, txid, authDigest=None): assert_equal(len(testnode.last_notfound.inv), 1) assert_equal(testnode.last_notfound.inv[0], self.cinv_for(txid, authDigest)) + def verify_invalid_cinv(self, testnode, conn, msg_type, expected_msg): + # Send p2p message "getdata" containing an invalid CInv message + getdatamsg = msg_getdata() + getdatamsg.inv = [CInv(msg_type, 1)] + with mininode_lock: + testnode.last_tx = None + testnode.last_notfound = None + testnode.send_message(getdatamsg) + + # Sync up with node after p2p messages delivered + testnode.sync_with_ping() + + # Verify that we get a reject message + expected = msg_reject() + expected.message = b"getdata" + expected.code = msg_reject.REJECT_MALFORMED + expected.reason = b"error parsing message" + assert_equal(conn.rejectMessage, expected) + + # Verify that we see the expected error on stderr + self.log_stderr.seek(0) + stderr = self.log_stderr.read().decode('utf-8') + self.log_stderr.truncate(0) + if expected_msg not in stderr: + raise AssertionError("Expected error \"" + expected_msg + "\" not found in:\n" + stderr) + def verify_disconnected(self, testnode, timeout=30): sleep_time = 0.05 while timeout > 0: @@ -115,8 +156,38 @@ def verify_disconnected(self, testnode, timeout=30): fail("Should have received pong") def run_test(self): + # Set up test nodes. + # - test_nodes[0] will only request v4 transactions + # - test_nodes[1] will only request v5 transactions + # - test_nodes[2] will test invalid v4 request using MSG_WTXID + # - test_nodes[3] will test invalid v5 request using MSG_TX + test_nodes = [] + connections = [] + + for i in range(4): + test_nodes.append(TestNode()) + connections.append(NodeConn( + '127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i], + protocol_version=NU5_PROTO_VERSION)) + test_nodes[i].add_connection(connections[i]) + + NetworkThread().start() # Start up network handling in another thread + [x.wait_for_verack() for x in test_nodes] + net_version = self.nodes[0].getnetworkinfo()["protocolversion"] if net_version < NU5_PROTO_VERSION: + # Sending a getdata message containing a MSG_WTX CInv message type + # results in a reject message. + self.verify_invalid_cinv( + test_nodes[0], connections[0], 5, + "Negotiated protocol version does not support CInv message type MSG_WTX", + ) + + # Sending a getdata message containing an invalid CInv message type + # results in a reject message. + self.verify_invalid_cinv( + test_nodes[1], connections[1], 0xffff, "Unknown CInv message type") + print("Node's block index is not NU5-aware, skipping remaining tests") return @@ -152,24 +223,6 @@ def run_test(self): # Wait for the mempools to sync. self.sync_all() - # Set up test nodes. - # - test_nodes[0] will only request v4 transactions - # - test_nodes[1] will only request v5 transactions - # - test_nodes[2] will test invalid v4 request using MSG_WTXID - # - test_nodes[3] will test invalid v5 request using MSG_TX - test_nodes = [] - connections = [] - - for i in range(4): - test_nodes.append(TestNode()) - connections.append(NodeConn( - '127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i], - protocol_version=NU5_PROTO_VERSION)) - test_nodes[i].add_connection(connections[i]) - - NetworkThread().start() # Start up network handling in another thread - [x.wait_for_verack() for x in test_nodes] - # # inv # @@ -207,7 +260,13 @@ def run_test(self): self.send_data_message(test_nodes[3], v5_txid) self.verify_disconnected(test_nodes[3]) + # Sending a getdata message containing an invalid CInv message type + # results in a reject message. + self.verify_invalid_cinv( + test_nodes[0], connections[0], 0xffff, "Unknown CInv message type") + [c.disconnect_node() for c in connections] + self.log_stderr.close() if __name__ == '__main__': Zip239Test().main() diff --git a/qa/rpc-tests/feature_zip244_blockcommitments.py b/qa/rpc-tests/feature_zip244_blockcommitments.py index 6113f856a4a..a0a5bde45f8 100755 --- a/qa/rpc-tests/feature_zip244_blockcommitments.py +++ b/qa/rpc-tests/feature_zip244_blockcommitments.py @@ -7,9 +7,14 @@ from test_framework.blocktools import derive_block_commitments_hash from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( + BLOSSOM_BRANCH_ID, + CANOPY_BRANCH_ID, + HEARTWOOD_BRANCH_ID, + NU5_BRANCH_ID, assert_equal, bytes_to_hex_str, hex_str_to_bytes, + nuparams, start_nodes, ) @@ -24,12 +29,10 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-nuparams=5ba81b19:1', # Overwinter - '-nuparams=76b809bb:1', # Sapling - '-nuparams=2bb40e60:201', # Blossom - '-nuparams=f5b9230b:201', # Heartwood - '-nuparams=e9ff75a6:201', # Canopy - '-nuparams=f919a198:205', # NU5 + nuparams(BLOSSOM_BRANCH_ID, 201), + nuparams(HEARTWOOD_BRANCH_ID, 201), + nuparams(CANOPY_BRANCH_ID, 201), + nuparams(NU5_BRANCH_ID, 205), '-nurejectoldversions=false', ]] * self.num_nodes) diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index 257d9893d04..789012284c7 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -6,9 +6,11 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( + NU5_BRANCH_ID, assert_equal, connect_nodes_bi, get_coinbase_address, + nuparams, start_nodes, wait_and_assert_operationid_status, ) @@ -17,6 +19,7 @@ SPROUT_TREE_EMPTY_ROOT = "59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7" SAPLING_TREE_EMPTY_ROOT = "3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb" +ORCHARD_TREE_EMPTY_ROOT = "2fd8e51a03d9bbe2dd809831b1497aeb68a6e37ddf707ced4aa2d8dff13529ae" NULL_FIELD = "0000000000000000000000000000000000000000000000000000000000000000" # Verify block header field 'hashFinalSaplingRoot' (returned in rpc as 'finalsaplingroot') @@ -25,17 +28,16 @@ class FinalSaplingRootTest(BitcoinTestFramework): def __init__(self): super().__init__() - self.num_nodes = 4 + self.num_nodes = 2 self.setup_clean_chain = True def setup_network(self, split=False): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-txindex' # Avoid JSONRPC error: No information available about transaction + '-txindex', # Avoid JSONRPC error: No information available about transaction + nuparams(NU5_BRANCH_ID, 210), + '-debug', ]] * self.num_nodes) connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - connect_nodes_bi(self.nodes,0,3) self.is_network_split=False self.sync_all() @@ -43,7 +45,7 @@ def run_test(self): self.nodes[0].generate(200) self.sync_all() - # Verfify genesis block contains null field for what is now called the final sapling root field. + # Verify genesis block contains null field for what is now called the final sapling root field. blk = self.nodes[0].getblock("0") assert_equal(blk["finalsaplingroot"], NULL_FIELD) treestate = self.nodes[0].z_gettreestate("0") @@ -52,13 +54,19 @@ def run_test(self): assert_equal(treestate["sprout"]["commitments"]["finalRoot"], SPROUT_TREE_EMPTY_ROOT) assert_equal(treestate["sprout"]["commitments"]["finalState"], "000000") - assert("skipHash" not in treestate["sprout"]) + assert "skipHash" not in treestate["sprout"] assert_equal(treestate["sapling"]["commitments"]["finalRoot"], NULL_FIELD) # There is no sapling state tree yet, and trying to find it in an earlier # block won't succeed (we're at genesis block), so skipHash is absent. - assert("finalState" not in treestate["sapling"]) - assert("skipHash" not in treestate["sapling"]) + assert "finalState" not in treestate["sapling"] + assert "skipHash" not in treestate["sapling"] + + assert_equal(treestate["orchard"]["commitments"]["finalRoot"], NULL_FIELD) + # There is no orchard state tree yet, and trying to find it in an earlier + # block won't succeed (we're at genesis block), so skipHash is absent. + assert "finalState" not in treestate["orchard"] + assert "skipHash" not in treestate["orchard"] # Verify all generated blocks contain the empty root of the Sapling tree. blockcount = self.nodes[0].getblockcount() @@ -70,14 +78,18 @@ def run_test(self): assert_equal(treestate["height"], height) assert_equal(treestate["hash"], self.nodes[0].getblockhash(height)) - assert("skipHash" not in treestate["sprout"]) + assert "skipHash" not in treestate["sprout"] assert_equal(treestate["sprout"]["commitments"]["finalRoot"], SPROUT_TREE_EMPTY_ROOT) assert_equal(treestate["sprout"]["commitments"]["finalState"], "000000") - assert("skipHash" not in treestate["sapling"]) + + assert "skipHash" not in treestate["sapling"] assert_equal(treestate["sapling"]["commitments"]["finalRoot"], SAPLING_TREE_EMPTY_ROOT) assert_equal(treestate["sapling"]["commitments"]["finalState"], "000000") + assert "skipHash" not in treestate["orchard"] + assert_equal(treestate["orchard"]["commitments"]["finalRoot"], NULL_FIELD) + # Node 0 shields some funds taddr0 = get_coinbase_address(self.nodes[0]) saplingAddr0 = self.nodes[0].z_getnewaddress('sapling') @@ -93,8 +105,8 @@ def run_test(self): # Verify the final Sapling root has changed blk = self.nodes[0].getblock("201") root = blk["finalsaplingroot"] - assert(root is not SAPLING_TREE_EMPTY_ROOT) - assert(root is not NULL_FIELD) + assert root is not SAPLING_TREE_EMPTY_ROOT + assert root is not NULL_FIELD # Verify there is a Sapling output description (its commitment was added to tree) result = self.nodes[0].getrawtransaction(mytxid, 1) @@ -105,8 +117,8 @@ def run_test(self): new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root) assert_equal(new_treestate["sprout"], treestate["sprout"]) - assert(new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"]) - assert(new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"]) + assert new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"] + assert new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"] assert_equal(len(new_treestate["sapling"]["commitments"]["finalRoot"]), 64) assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 70) treestate = new_treestate @@ -131,10 +143,8 @@ def run_test(self): # Mine a block with a Sprout shielded tx and verify the final Sapling root does not change zaddr1 = self.nodes[1].z_getnewaddress('sprout') - recipients = [] - recipients.append({"address": zaddr1, "amount": Decimal('10')}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0) - wait_and_assert_operationid_status(self.nodes[0], myopid) + result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr1, 0, 1) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) self.sync_all() self.nodes[0].generate(1) @@ -147,8 +157,8 @@ def run_test(self): new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root) assert_equal(new_treestate["sapling"], treestate["sapling"]) - assert(new_treestate["sprout"]["commitments"]["finalRoot"] != treestate["sprout"]["commitments"]["finalRoot"]) - assert(new_treestate["sprout"]["commitments"]["finalState"] != treestate["sprout"]["commitments"]["finalState"]) + assert new_treestate["sprout"]["commitments"]["finalRoot"] != treestate["sprout"]["commitments"]["finalRoot"] + assert new_treestate["sprout"]["commitments"]["finalState"] != treestate["sprout"]["commitments"]["finalState"] assert_equal(len(new_treestate["sprout"]["commitments"]["finalRoot"]), 64) assert_equal(len(new_treestate["sprout"]["commitments"]["finalState"]), 134) treestate = new_treestate @@ -166,7 +176,7 @@ def run_test(self): assert_equal(len(self.nodes[0].getblock("205")["tx"]), 2) assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal("12.34")) - assert(root is not self.nodes[0].getblock("205")["finalsaplingroot"]) + assert root is not self.nodes[0].getblock("205")["finalsaplingroot"] # Verify there is a Sapling output description (its commitment was added to tree) result = self.nodes[0].getrawtransaction(mytxid, 1) @@ -174,8 +184,8 @@ def run_test(self): new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sprout"], treestate["sprout"]) - assert(new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"]) - assert(new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"]) + assert new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"] + assert new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"] assert_equal(len(new_treestate["sapling"]["commitments"]["finalRoot"]), 64) assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 136) treestate = new_treestate @@ -202,6 +212,21 @@ def run_test(self): assert_equal(new_treestate["sprout"], treestate["sprout"]) assert_equal(new_treestate["sapling"], treestate["sapling"]) + # Activate NU5; more testing should be added once we can mine orchard transactions. + self.sync_all() + self.nodes[0].generate(4) + self.sync_all() + new_treestate = self.nodes[0].z_gettreestate(str(-1)) + + # sprout and sapling results should not change + assert_equal(new_treestate["sprout"], treestate["sprout"]) + assert_equal(new_treestate["sapling"], treestate["sapling"]) + + assert "skipHash" not in treestate["orchard"] + assert_equal(new_treestate["orchard"]["commitments"]["finalRoot"], ORCHARD_TREE_EMPTY_ROOT) + assert_equal(new_treestate["orchard"]["commitments"]["finalState"], "00") + pass + if __name__ == '__main__': FinalSaplingRootTest().main() diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index de8dc39e435..f75470306c4 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -73,7 +73,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs ############################## # simple test with two coins # diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 223132da48f..da3f638f991 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -3,63 +3,185 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from io import BytesIO +import codecs from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, connect_nodes_bi, \ - start_nodes - +from test_framework.util import ( + assert_equal, + CANOPY_BRANCH_ID, + NU5_BRANCH_ID, + hex_str_to_bytes, + nuparams, + start_nodes, + wait_and_assert_operationid_status, +) +from test_framework.mininode import ( + CTransaction, + uint256_from_str, +) +from test_framework.blocktools import ( + create_block +) +from decimal import Decimal class GetBlockTemplateTest(BitcoinTestFramework): ''' - Test getblocktemplate. + Test getblocktemplate, ensure that a block created from its result + can be submitted and accepted. ''' def __init__(self): super().__init__() - self.num_nodes = 2 + self.num_nodes = 1 self.setup_clean_chain = True def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - self.is_network_split=False + args = [ + nuparams(CANOPY_BRANCH_ID, 115), + nuparams(NU5_BRANCH_ID, 130), + ] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args] * self.num_nodes) + self.is_network_split = False + self.node = self.nodes[0] + + def add_nu5_v4_tx_to_mempool(self): + node = self.node + # sprout to transparent (v4) + recipients = [{"address": self.transparent_addr, "amount": Decimal('0.1')}] + myopid = node.z_sendmany(self.sprout_addr, recipients) + wait_and_assert_operationid_status(node, myopid) + + def add_transparent_tx_to_mempool(self): + node = self.node + # transparent to transparent (v5 after nu5) + outputs = {self.transparent_addr: 0.1} + node.sendmany('', outputs) + + def gbt_submitblock(self, nu5_active): + node = self.node + mempool_tx_list = node.getrawmempool() + + gbt = node.getblocktemplate() + + # make sure no transactions were left out (or added) + assert_equal(len(mempool_tx_list), len(gbt['transactions'])) + assert_equal(set(mempool_tx_list), set([tx['hash'] for tx in gbt['transactions']])) + + prevhash = int(gbt['previousblockhash'], 16) + nTime = gbt['mintime'] + nBits = int(gbt['bits'], 16) + + if nu5_active: + blockcommitmentshash = int(gbt['defaultroots']['blockcommitmentshash'], 16) + else: + blockcommitmentshash = int(gbt['defaultroots']['chainhistoryroot'], 16) + assert 'blockcommitmentshash' not in gbt['defaultroots'] + # Confirm that the legacy fields match this default value. + assert_equal(blockcommitmentshash, int(gbt['blockcommitmentshash'], 16)) + assert_equal(blockcommitmentshash, int(gbt['lightclientroothash'], 16)) + assert_equal(blockcommitmentshash, int(gbt['finalsaplingroothash'], 16)) + + f = BytesIO(hex_str_to_bytes(gbt['coinbasetxn']['data'])) + coinbase = CTransaction() + coinbase.deserialize(f) + coinbase.calc_sha256() + assert_equal(coinbase.hash, gbt['coinbasetxn']['hash']) + assert_equal(coinbase.auth_digest_hex, gbt['coinbasetxn']['authdigest']) + + block = create_block(prevhash, coinbase, nTime, nBits, blockcommitmentshash) + + # copy the non-coinbase transactions from the block template to the block + for gbt_tx in gbt['transactions']: + f = BytesIO(hex_str_to_bytes(gbt_tx['data'])) + tx = CTransaction() + tx.deserialize(f) + tx.calc_sha256() + assert_equal(tx.auth_digest_hex, node.getrawtransaction(tx.hash, 1)['authdigest']) + block.vtx.append(tx) + block.hashMerkleRoot = int(gbt['defaultroots']['merkleroot'], 16) + assert_equal(block.hashMerkleRoot, block.calc_merkle_root(), "merkleroot") + assert_equal(len(block.vtx), len(gbt['transactions']) + 1, "number of transactions") + assert_equal(block.hashPrevBlock, int(gbt['previousblockhash'], 16), "prevhash") + if nu5_active: + assert_equal(uint256_from_str(block.calc_auth_data_root()), int(gbt['defaultroots']['authdataroot'], 16)) + else: + assert 'authdataroot' not in gbt['defaultroots'] + block.solve() + block.calc_sha256() + + submitblock_reply = node.submitblock(codecs.encode(block.serialize(), 'hex_codec')) + assert_equal(None, submitblock_reply) + assert_equal(block.hash, node.getbestblockhash()) + # Wait until the wallet has been notified of all blocks, so that it doesn't try to + # double-spend transparent coins in subsequent test phases. self.sync_all() def run_test(self): - node = self.nodes[0] - node.generate(1) # Mine a block to leave initial block download - - # Test 1: Default to coinbasetxn - tmpl = node.getblocktemplate() - assert('coinbasetxn' in tmpl) - assert('coinbasevalue' not in tmpl) - - # Test 2: Get coinbasetxn if requested - tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn']}) - assert('coinbasetxn' in tmpl) - assert('coinbasevalue' not in tmpl) - - # Test 3: coinbasevalue not supported if requested - tmpl = node.getblocktemplate({'capabilities': ['coinbasevalue']}) - assert('coinbasetxn' in tmpl) - assert('coinbasevalue' not in tmpl) - - # Test 4: coinbasevalue not supported if both requested - tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn', 'coinbasevalue']}) - assert('coinbasetxn' in tmpl) - assert('coinbasevalue' not in tmpl) - - # Test 5: General checks - tmpl = node.getblocktemplate() - assert_equal(16, len(tmpl['noncerange'])) - - # Test 6: coinbasetxn checks - assert('foundersreward' in tmpl['coinbasetxn']) - assert(tmpl['coinbasetxn']['required']) - - # Test 7: hashFinalSaplingRoot checks - assert('finalsaplingroothash' in tmpl) - finalsaplingroothash = '3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb' - assert_equal(finalsaplingroothash, tmpl['finalsaplingroothash']) + node = self.node + + # Generate Sprout funds before Canopy activates; using the Sprout address will + # force the generation of v4 transactions from NU5. + print("Generating pre-Canopy blocks to create sprout funds") + # coinbase only becomes mature after 100 blocks, so make one mature. + node.generate(105) + + self.sprout_addr = node.z_getnewaddress('sprout') + myopid = node.z_shieldcoinbase('*', self.sprout_addr)['opid'] + wait_and_assert_operationid_status(node, myopid) + + self.transparent_addr = node.getnewaddress() + node.generate(15) + + # at height 120, NU5 is not active + assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'pending') + + print("Testing getblocktemplate for pre-NU5") + + # Only the coinbase; this covers the case where the Merkle root + # is equal to the coinbase txid. + print("- only coinbase") + self.gbt_submitblock(False) + + # Adding one transaction triggering a single Merkle digest. + print("- one transaction (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(False) + + # Adding two transactions to trigger hash Merkle root edge case. + print("- two transactions (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(False) + + # Activate NU5, repeat the above cases + node.generate(7) + assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'active') + + print("Testing getblocktemplate for post-NU5") + + # Only the coinbase; this covers the case where the block authdata root + # is equal to the coinbase authdata + print("- only coinbase") + self.gbt_submitblock(True) + + # Adding one transaction triggering a single Merkle digest. + print("- one transaction (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) + + # Adding two transactions to trigger hash Merkle root edge case. + print("- two transactions (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) + + # Adding both v4 and v5 to cover legacy auth digest. + print("- both v4 and v5 transactions (plus coinbase)") + self.add_nu5_v4_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) + if __name__ == '__main__': GetBlockTemplateTest().main() diff --git a/qa/rpc-tests/getmininginfo.py b/qa/rpc-tests/getmininginfo.py new file mode 100755 index 00000000000..a1edaf12e37 --- /dev/null +++ b/qa/rpc-tests/getmininginfo.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import start_nodes + + +class GetMiningInfoTest(BitcoinTestFramework): + ''' + Test getmininginfo. + ''' + + def __init__(self): + super().__init__() + self.num_nodes = 1 + self.setup_clean_chain = True + + def setup_network(self, split=False): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.is_network_split = False + self.sync_all() + + def run_test(self): + node = self.nodes[0] + + info = node.getmininginfo() + assert(info['blocks'] == 0) + # No blocks have been mined yet, so these fields should not be present. + assert('currentblocksize' not in info) + assert('currentblocktx' not in info) + + node.generate(1) + + info = node.getmininginfo() + assert(info['blocks'] == 1) + # One block has been mined, so these fields should now be present. + assert('currentblocksize' in info) + assert('currentblocktx' in info) + assert(info['currentblocksize'] > 0) + # The transaction count doesn't include the coinbase + assert(info['currentblocktx'] == 0) + + +if __name__ == '__main__': + GetMiningInfoTest().main() diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index 7463dab5c8d..4fb916e10fe 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -26,10 +26,6 @@ class InvalidBlockRequestTest(ComparisonTestFramework): ''' Can either run this test as 1 node with expected answers, or two and compare them. Change the "outcome" variable from each TestInstance object to only do the comparison. ''' - def __init__(self): - super().__init__() - self.num_nodes = 1 - def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py index 6b850a19804..8ec448f5066 100755 --- a/qa/rpc-tests/invalidtxrequest.py +++ b/qa/rpc-tests/invalidtxrequest.py @@ -20,10 +20,6 @@ class InvalidTxRequestTest(ComparisonTestFramework): ''' Can either run this test as 1 node with expected answers, or two and compare them. Change the "outcome" variable from each TestInstance object to only do the comparison. ''' - def __init__(self): - super().__init__() - self.num_nodes = 1 - def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index ccba07ea9fc..d567be3a5b9 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -40,13 +40,13 @@ def run_test(self): bitcoind_processes[0].wait() # Restart node 0 nodes[0] = start_node(0, self.options.tmpdir) - # Keep creating keys - addr = nodes[0].getnewaddress() + # We can't create any external addresses, which don't use the keypool. + # We should get an error that we need to unlock the wallet. try: addr = nodes[0].getnewaddress() - raise AssertionError('Keypool should be exhausted after one address') + raise AssertionError('Wallet should be locked.') except JSONRPCException as e: - assert(e.error['code']==-12) + assert_equal(e.error['code'], -13) # put three new keys in the keypool nodes[0].walletpassphrase('test', 12000) diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index 05e057a8b9f..14d5df2c2a9 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -6,7 +6,12 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.mininode import NU5_PROTO_VERSION from test_framework.util import ( + BLOSSOM_BRANCH_ID, + CANOPY_BRANCH_ID, + HEARTWOOD_BRANCH_ID, + NU5_BRANCH_ID, assert_equal, assert_true, + nuparams, start_node, connect_nodes, wait_and_assert_operationid_status, get_coinbase_address ) @@ -25,10 +30,10 @@ def __init__(self): def setup_network(self): args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000", - "-nuparams=2bb40e60:200", # Blossom - "-nuparams=f5b9230b:210", # Heartwood - "-nuparams=e9ff75a6:220", # Canopy - "-nuparams=f919a198:230", # NU5 + nuparams(BLOSSOM_BRANCH_ID, 200), + nuparams(HEARTWOOD_BRANCH_ID, 210), + nuparams(CANOPY_BRANCH_ID, 220), + nuparams(NU5_BRANCH_ID, 230), ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py index d0a67544d8e..fd772bfd195 100755 --- a/qa/rpc-tests/mergetoaddress_mixednotes.py +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -29,8 +29,8 @@ def run_test(self): saplingAddr = self.nodes[0].z_getnewaddress('sapling') t_addr = self.nodes[1].getnewaddress() - opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) - wait_and_assert_operationid_status(self.nodes[0], opid) + result = self.nodes[0].z_shieldcoinbase(coinbase_addr, sproutAddr, 0, 1) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index 4b7f1468075..2945861b39a 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -75,7 +75,7 @@ def run_test(self): txid_spent = txin_spent["txid"] txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 - # We cant find the block from a fully-spent tx + # We can't find the block from a fully-spent tx assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent]) # ...but we can if we specify the block assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent]) diff --git a/qa/rpc-tests/mining_shielded_coinbase.py b/qa/rpc-tests/mining_shielded_coinbase.py index 83c34401118..9d9fc517f53 100755 --- a/qa/rpc-tests/mining_shielded_coinbase.py +++ b/qa/rpc-tests/mining_shielded_coinbase.py @@ -6,10 +6,12 @@ from decimal import Decimal from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework -from test_framework.mininode import nuparams +from test_framework.mininode import COIN, nuparams from test_framework.util import ( BLOSSOM_BRANCH_ID, HEARTWOOD_BRANCH_ID, + CANOPY_BRANCH_ID, + NU5_BRANCH_ID, assert_equal, assert_raises, bitcoind_processes, @@ -28,8 +30,12 @@ def __init__(self): def start_node_with(self, index, extra_args=[]): args = [ + '-experimentalfeatures', + '-orchardwallet', nuparams(BLOSSOM_BRANCH_ID, 1), nuparams(HEARTWOOD_BRANCH_ID, 10), + nuparams(CANOPY_BRANCH_ID, 20), + nuparams(NU5_BRANCH_ID, 20), "-nurejectoldversions=false", ] return start_node(index, self.options.tmpdir, args + extra_args) @@ -117,5 +123,50 @@ def run_test (self): assert_equal(self.nodes[0].z_getbalance(node0_taddr), 2) assert_equal(self.nodes[1].z_getbalance(node1_zaddr), 1) + # Generate a Unified Address for node 1 + self.nodes[1].z_getnewaccount() + node1_addr0 = self.nodes[1].z_getaddressforaccount(0) + assert_equal(node1_addr0['account'], 0) + assert_equal(set(node1_addr0['pools']), set(['transparent', 'sapling', 'orchard'])) + node1_ua = node1_addr0['unifiedaddress'] + + # Set node 1's miner address to the UA + self.nodes[1].stop() + bitcoind_processes[1].wait() + self.nodes[1] = self.start_node_with(1, [ + "-mineraddress=%s" % node1_ua, + ]) + connect_nodes(self.nodes[1], 0) + + # The UA starts with zero balance. + assert_equal(self.nodes[1].z_getbalanceforaccount(0)['pools'], {}) + + # Node 1 can mine blocks because the miner selects the Sapling receiver + # of its UA. + print("Mining block with node 1") + self.nodes[1].generate(1) + self.sync_all() + + # The UA balance should show that Sapling funds were received. + assert_equal(self.nodes[1].z_getbalanceforaccount(0)['pools'], { + 'sapling': {'valueZat': 5 * COIN }, + }) + + # Activate NU5 + print("Activating NU5") + self.nodes[0].generate(7) + self.sync_all() + + # Now any block mined by node 1 should use the Orchard receiver of its UA. + print("Mining block with node 1") + self.nodes[1].generate(1) + self.sync_all() + assert_equal(self.nodes[1].z_getbalanceforaccount(0)['pools'], { + 'sapling': {'valueZat': 5 * COIN }, + # 6.25 ZEC because the FR always ends when Canopy activates, and + # regtest has no defined funding streams. + 'orchard': {'valueZat': 6.25 * COIN }, + }) + if __name__ == '__main__': ShieldCoinbaseTest().main() diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index 40614d2e810..59cdbd60c45 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -27,7 +27,7 @@ def run_test(self): ########################### assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point self.nodes[2].setban("127.0.0.1", "add") - time.sleep(3) #wait till the nodes are disconected + time.sleep(3) #wait till the nodes are disconnected assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point assert_equal(len(self.nodes[2].listbanned()), 1) self.nodes[2].clearbanned() diff --git a/qa/rpc-tests/nuparams.py b/qa/rpc-tests/nuparams.py new file mode 100755 index 00000000000..4482f116a4e --- /dev/null +++ b/qa/rpc-tests/nuparams.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + start_nodes, + nuparams, + HEARTWOOD_BRANCH_ID, + NU5_BRANCH_ID, +) + + +class NuparamsTest(BitcoinTestFramework): + ''' + Test that unspecified network upgrades are activated automatically; + this is really more of a test of the test framework. + ''' + + def __init__(self): + super().__init__() + self.num_nodes = 1 + self.setup_clean_chain = True + + def setup_network(self, split=False): + args = [[ + nuparams(HEARTWOOD_BRANCH_ID, 3), + nuparams(NU5_BRANCH_ID, 5), + ] * self.num_nodes] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, args) + self.is_network_split = False + self.sync_all() + + def run_test(self): + node = self.nodes[0] + # No blocks have been created, only the genesis block exists (height 0) + bci = node.getblockchaininfo() + assert_equal(bci['blocks'], 0) + upgrades = bci['upgrades'] + + overwinter = upgrades['5ba81b19'] + assert_equal(overwinter['name'], 'Overwinter') + assert_equal(overwinter['activationheight'], 1) + assert_equal(overwinter['status'], 'pending') + + sapling = upgrades['76b809bb'] + assert_equal(sapling['name'], 'Sapling') + assert_equal(sapling['activationheight'], 1) + assert_equal(sapling['status'], 'pending') + + blossom = upgrades['2bb40e60'] + assert_equal(blossom['name'], 'Blossom') + assert_equal(blossom['activationheight'], 3) + assert_equal(blossom['status'], 'pending') + + heartwood = upgrades['f5b9230b'] + assert_equal(heartwood['name'], 'Heartwood') + assert_equal(heartwood['activationheight'], 3) + assert_equal(heartwood['status'], 'pending') + + canopy = upgrades['e9ff75a6'] + assert_equal(canopy['name'], 'Canopy') + assert_equal(canopy['activationheight'], 5) + assert_equal(canopy['status'], 'pending') + + nu5 = upgrades['37519621'] + assert_equal(nu5['name'], 'NU5') + assert_equal(nu5['activationheight'], 5) + assert_equal(nu5['status'], 'pending') + + node.generate(1) + + # start_node() hardcodes Sapling and Overwinter to activate a height 1 + bci = node.getblockchaininfo() + assert_equal(bci['blocks'], 1) + upgrades = bci['upgrades'] + + overwinter = upgrades['5ba81b19'] + assert_equal(overwinter['name'], 'Overwinter') + assert_equal(overwinter['activationheight'], 1) + assert_equal(overwinter['status'], 'active') + + sapling = upgrades['76b809bb'] + assert_equal(sapling['name'], 'Sapling') + assert_equal(sapling['activationheight'], 1) + assert_equal(sapling['status'], 'active') + + blossom = upgrades['2bb40e60'] + assert_equal(blossom['name'], 'Blossom') + assert_equal(blossom['activationheight'], 3) + assert_equal(blossom['status'], 'pending') + + heartwood = upgrades['f5b9230b'] + assert_equal(heartwood['name'], 'Heartwood') + assert_equal(heartwood['activationheight'], 3) + assert_equal(heartwood['status'], 'pending') + + canopy = upgrades['e9ff75a6'] + assert_equal(canopy['name'], 'Canopy') + assert_equal(canopy['activationheight'], 5) + assert_equal(canopy['status'], 'pending') + + nu5 = upgrades['37519621'] + assert_equal(nu5['name'], 'NU5') + assert_equal(nu5['activationheight'], 5) + assert_equal(nu5['status'], 'pending') + + node.generate(1) + bci = node.getblockchaininfo() + assert_equal(bci['blocks'], 2) + upgrades = bci['upgrades'] + + overwinter = upgrades['5ba81b19'] + assert_equal(overwinter['name'], 'Overwinter') + assert_equal(overwinter['activationheight'], 1) + assert_equal(overwinter['status'], 'active') + + sapling = upgrades['76b809bb'] + assert_equal(sapling['name'], 'Sapling') + assert_equal(sapling['activationheight'], 1) + assert_equal(sapling['status'], 'active') + + blossom = upgrades['2bb40e60'] + assert_equal(blossom['name'], 'Blossom') + assert_equal(blossom['activationheight'], 3) + assert_equal(blossom['status'], 'pending') + + heartwood = upgrades['f5b9230b'] + assert_equal(heartwood['name'], 'Heartwood') + assert_equal(heartwood['activationheight'], 3) + assert_equal(heartwood['status'], 'pending') + + canopy = upgrades['e9ff75a6'] + assert_equal(canopy['name'], 'Canopy') + assert_equal(canopy['activationheight'], 5) + assert_equal(canopy['status'], 'pending') + + nu5 = upgrades['37519621'] + assert_equal(nu5['name'], 'NU5') + assert_equal(nu5['activationheight'], 5) + assert_equal(nu5['status'], 'pending') + + node.generate(2) + bci = node.getblockchaininfo() + assert_equal(bci['blocks'], 4) + upgrades = bci['upgrades'] + + overwinter = upgrades['5ba81b19'] + assert_equal(overwinter['name'], 'Overwinter') + assert_equal(overwinter['activationheight'], 1) + assert_equal(overwinter['status'], 'active') + + sapling = upgrades['76b809bb'] + assert_equal(sapling['name'], 'Sapling') + assert_equal(sapling['activationheight'], 1) + assert_equal(sapling['status'], 'active') + + blossom = upgrades['2bb40e60'] + assert_equal(blossom['name'], 'Blossom') + assert_equal(blossom['activationheight'], 3) + assert_equal(blossom['status'], 'active') + + heartwood = upgrades['f5b9230b'] + assert_equal(heartwood['name'], 'Heartwood') + assert_equal(heartwood['activationheight'], 3) + assert_equal(heartwood['status'], 'active') + + canopy = upgrades['e9ff75a6'] + assert_equal(canopy['name'], 'Canopy') + assert_equal(canopy['activationheight'], 5) + assert_equal(canopy['status'], 'pending') + + nu5 = upgrades['37519621'] + assert_equal(nu5['name'], 'NU5') + assert_equal(nu5['activationheight'], 5) + assert_equal(nu5['status'], 'pending') + + node.generate(1) + bci = node.getblockchaininfo() + assert_equal(bci['blocks'], 5) + upgrades = bci['upgrades'] + + overwinter = upgrades['5ba81b19'] + assert_equal(overwinter['name'], 'Overwinter') + assert_equal(overwinter['activationheight'], 1) + assert_equal(overwinter['status'], 'active') + + sapling = upgrades['76b809bb'] + assert_equal(sapling['name'], 'Sapling') + assert_equal(sapling['activationheight'], 1) + assert_equal(sapling['status'], 'active') + + blossom = upgrades['2bb40e60'] + assert_equal(blossom['name'], 'Blossom') + assert_equal(blossom['activationheight'], 3) + assert_equal(blossom['status'], 'active') + + heartwood = upgrades['f5b9230b'] + assert_equal(heartwood['name'], 'Heartwood') + assert_equal(heartwood['activationheight'], 3) + assert_equal(heartwood['status'], 'active') + + canopy = upgrades['e9ff75a6'] + assert_equal(canopy['name'], 'Canopy') + assert_equal(canopy['activationheight'], 5) + assert_equal(canopy['status'], 'active') + + nu5 = upgrades['37519621'] + assert_equal(nu5['name'], 'NU5') + assert_equal(nu5['activationheight'], 5) + assert_equal(nu5['status'], 'active') + + +if __name__ == '__main__': + NuparamsTest().main() diff --git a/qa/rpc-tests/orchard_reorg.py b/qa/rpc-tests/orchard_reorg.py new file mode 100755 index 00000000000..58d0bf8d9d7 --- /dev/null +++ b/qa/rpc-tests/orchard_reorg.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# Copyright (c) 2022 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +# +# Test the effect of reorgs on the Orchard commitment tree. +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + BLOSSOM_BRANCH_ID, + HEARTWOOD_BRANCH_ID, + CANOPY_BRANCH_ID, + NU5_BRANCH_ID, + assert_equal, + get_coinbase_address, + nuparams, + start_nodes, + wait_and_assert_operationid_status, +) + +from finalsaplingroot import ORCHARD_TREE_EMPTY_ROOT + +from decimal import Decimal + +class OrchardReorgTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = True + + def setup_nodes(self): + return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ + nuparams(BLOSSOM_BRANCH_ID, 1), + nuparams(HEARTWOOD_BRANCH_ID, 5), + nuparams(CANOPY_BRANCH_ID, 5), + nuparams(NU5_BRANCH_ID, 10), + '-nurejectoldversions=false', + '-experimentalfeatures', + '-orchardwallet', + # '-debug', + ]] * self.num_nodes) + + def run_test(self): + # Activate NU5 so we can test Orchard. + self.nodes[0].generate(10) + self.sync_all() + + # Generate a UA with only an Orchard receiver. + account = self.nodes[0].z_getnewaccount()['account'] + addr = self.nodes[0].z_getaddressforaccount(account, ['orchard']) + assert_equal(addr['account'], account) + assert_equal(set(addr['pools']), set(['orchard'])) + ua = addr['unifiedaddress'] + + # Before mining any Orchard notes, finalorchardroot should be the empty Orchard root. + assert_equal( + ORCHARD_TREE_EMPTY_ROOT, + self.nodes[0].getblock(self.nodes[0].getbestblockhash())['finalorchardroot'], + ) + + # finalorchardroot should not change if we mine additional blocks without Orchard notes. + self.nodes[0].generate(100) + self.sync_all() + assert_equal( + ORCHARD_TREE_EMPTY_ROOT, + self.nodes[0].getblock(self.nodes[0].getbestblockhash())['finalorchardroot'], + ) + + # Create an Orchard note. + recipients = [{'address': ua, 'amount': Decimal('12.5')}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], opid) + + # After mining a block, finalorchardroot should have changed. + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + orchardroot_oneleaf = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['finalorchardroot'] + print("Root of Orchard commitment tree with one leaf:", orchardroot_oneleaf) + assert(orchardroot_oneleaf != ORCHARD_TREE_EMPTY_ROOT) + + # finalorchardroot should not change if we mine additional blocks without Orchard notes. + self.nodes[0].generate(4) + self.sync_all() + assert_equal( + orchardroot_oneleaf, + self.nodes[0].getblock(self.nodes[0].getbestblockhash())['finalorchardroot'], + ) + + # Split the network so we can test the effect of a reorg. + print("Splitting the network") + self.split_network() + + # Create another Orchard note on node 0. + recipients = [{'address': ua, 'amount': Decimal('12.5')}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], opid) + + # Mine two blocks on node 0. + print("Mining 2 blocks on node 0") + self.nodes[0].generate(2) + self.sync_all() + orchardroot_twoleaf = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['finalorchardroot'] + print("Root of Orchard commitment tree with two leaves:", orchardroot_twoleaf) + assert(orchardroot_twoleaf != ORCHARD_TREE_EMPTY_ROOT) + assert(orchardroot_twoleaf != orchardroot_oneleaf) + + # Generate 10 blocks on node 2. + print("Mining alternate chain on node 2") + self.nodes[2].generate(10) + self.sync_all() + assert_equal( + orchardroot_oneleaf, + self.nodes[2].getblock(self.nodes[2].getbestblockhash())['finalorchardroot'], + ) + + # Reconnect the nodes; node 0 will re-org to node 2's chain. + print("Re-joining the network so that node 0 reorgs") + self.join_network() + + # Verify that node 0's latest Orchard root matches what we expect. + orchardroot_postreorg = self.nodes[0].getblock(self.nodes[2].getbestblockhash())['finalorchardroot'] + print("Root of Orchard commitment tree after reorg:", orchardroot_postreorg) + assert_equal(orchardroot_postreorg, orchardroot_oneleaf) + + +if __name__ == '__main__': + OrchardReorgTest().main() diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index 2307cfcebc5..17cc3572c15 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -39,7 +39,6 @@ class FullBlockTest(ComparisonTestFramework): Change the "outcome" variable from each TestInstance object to only do the comparison. ''' def __init__(self): super().__init__() - self.num_nodes = 1 self.block_heights = {} self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes(b"horsebattery") @@ -159,7 +158,7 @@ def tip(number): yield test - # Start by bulding a couple of blocks on top (which output is spent is in parentheses): + # Start by building a couple of blocks on top (which output is spent is in parentheses): # genesis -> b1 (0) -> b2 (1) out0 = get_spendable_output() block(1, spend=out0) diff --git a/qa/rpc-tests/paymentdisclosure.py b/qa/rpc-tests/paymentdisclosure.py deleted file mode 100755 index db9add40718..00000000000 --- a/qa/rpc-tests/paymentdisclosure.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2017 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php . - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, \ - start_node, connect_nodes_bi, wait_and_assert_operationid_status, \ - get_coinbase_address, DEFAULT_FEE - -from decimal import Decimal - -class PaymentDisclosureTest (BitcoinTestFramework): - - def __init__(self): - super().__init__() - self.num_nodes = 3 - self.setup_clean_chain = True - - def setup_network(self, split=False): - args = ['-debug=zrpcunsafe,paymentdisclosure', '-experimentalfeatures', '-paymentdisclosure', '-txindex=1'] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - # node 2 does not enable payment disclosure - args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-txindex=1'] - self.nodes.append(start_node(2, self.options.tmpdir, args2)) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() - - def run_test (self): - print("Mining blocks...") - - self.nodes[0].generate(4) - self.sync_all() - walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 40) - assert_equal(walletinfo['balance'], 0) - self.sync_all() - self.nodes[2].generate(3) - self.sync_all() - self.nodes[1].generate(101) - self.sync_all() - assert_equal(self.nodes[0].getbalance(), 40) - assert_equal(self.nodes[1].getbalance(), 10) - assert_equal(self.nodes[2].getbalance(), 30) - - mytaddr = get_coinbase_address(self.nodes[0]) - myzaddr = self.nodes[0].z_getnewaddress('sprout') - - # Check that Node 2 has payment disclosure disabled. - try: - self.nodes[2].z_getpaymentdisclosure("invalidtxid", 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("payment disclosure is disabled" in errorString) - - # Check that Node 0 returns an error for an unknown txid - try: - self.nodes[0].z_getpaymentdisclosure("invalidtxid", 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("No information available about transaction" in errorString) - - # Shield coinbase utxos from node 0 of value 40, default fee - recipients = [{"address": myzaddr, "amount": Decimal('40.0') - DEFAULT_FEE}] - myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - - # Check the tx has joinsplits - assert( len(self.nodes[0].getrawtransaction("" + txid, 1)["vjoinsplit"]) > 0 ) - - # Sync mempools - self.sync_all() - - # Confirm that you can't create a payment disclosure for an unconfirmed tx - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - # Mine tx - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that Node 1 cannot create a payment disclosure for a transaction which does not impact its wallet - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction does not belong to the wallet" in errorString) - - # Check that an invalid joinsplit index is rejected - try: - self.nodes[0].z_getpaymentdisclosure(txid, 1, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid js_index" in errorString) - - try: - self.nodes[0].z_getpaymentdisclosure(txid, -1, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid js_index" in errorString) - - # Check that an invalid output index is rejected - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 2) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid output_index" in errorString) - - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, -1) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid output_index" in errorString) - - # Ask Node 0 to create and validate a payment disclosure for output 0 - message = "Here is proof of my payment!" - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, message) - result = self.nodes[0].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - output_value_sum = Decimal(result["value"]) - - # Ask Node 1 to confirm the payment disclosure is valid - result = self.nodes[1].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - assert_equal(result["message"], message) - assert_equal(result["value"], output_value_sum) - - # Confirm that payment disclosure begins with prefix zpd: - assert(pd.startswith("zpd:")) - - # Confirm that payment disclosure without prefix zpd: fails validation - try: - self.nodes[1].z_validatepaymentdisclosure(pd[4:]) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("payment disclosure prefix not found" in errorString) - - # Check that total value of output index 0 and index 1 should equal shielding amount of 40 less standard fee. - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 1) - result = self.nodes[0].z_validatepaymentdisclosure(pd) - output_value_sum += Decimal(result["value"]) - assert_equal(output_value_sum, Decimal('40.0') - DEFAULT_FEE) - - # Create a z->z transaction, sending shielded funds from node 0 to node 1 - node1zaddr = self.nodes[1].z_getnewaddress('sprout') - recipients = [{"address":node1zaddr, "amount":Decimal('1')}] - myopid = self.nodes[0].z_sendmany(myzaddr, recipients) - txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that Node 0 can create a valid payment disclosure - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, "a message of your choice") - result = self.nodes[0].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - - # Confirm that Node 1, even as recipient of shielded funds, cannot create a payment disclosure - # as the transaction was created by Node 0 and Node 1's payment disclosure database does not - # contain the necessary data to do so, where the data would only have been available on Node 0 - # when executing z_shieldcoinbase. - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Could not find payment disclosure info for the given joinsplit output" in errorString) - - # Payment disclosures cannot be created for transparent transactions. - txid = self.nodes[2].sendtoaddress(mytaddr, 1.0) - self.sync_all() - - # No matter the type of transaction, if it has not been confirmed, it is ignored. - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that a payment disclosure can only be generated for a shielded transaction. - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction is not a shielded transaction" in errorString) - -if __name__ == '__main__': - PaymentDisclosureTest().main() diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 2916f76fefd..95a18ca920e 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -152,7 +152,7 @@ def reorg_test(self): print("Invalidating block at height:",invalidheight,badhash) self.nodes[1].invalidateblock(badhash) - # We've now switched to our previously mined-24 block fork on node 1, but thats not what we want + # We've now switched to our previously mined-24 block fork on node 1, but that's not what we want # So invalidate that fork as well, until we're on the same chain as node 0/2 (but at an ancestor 288 blocks ago) mainchainhash = self.nodes[0].getblockhash(invalidheight - 1) curhash = self.nodes[1].getblockhash(invalidheight - 1) @@ -210,7 +210,7 @@ def reorg_back(self): goalbesthash = self.mainchainhash2 # As of 0.10 the current block download logic is not able to reorg to the original chain created in - # create_chain_with_stale_blocks because it doesn't know of any peer thats on that chain from which to + # create_chain_with_stale_blocks because it doesn't know of any peer that's on that chain from which to # redownload its missing blocks. # Invalidate the reorg_test chain in node 0 as well, it can successfully switch to the original chain # because it has all the block data. diff --git a/qa/rpc-tests/remove_sprout_shielding.py b/qa/rpc-tests/remove_sprout_shielding.py index 9a84d19f2e2..e57ef30034b 100755 --- a/qa/rpc-tests/remove_sprout_shielding.py +++ b/qa/rpc-tests/remove_sprout_shielding.py @@ -41,6 +41,7 @@ def run_test (self): # Shield coinbase to Sprout on node 0. Should pass sprout_addr = self.nodes[0].z_getnewaddress('sprout') + sprout_addr_node2 = self.nodes[2].z_getnewaddress('sprout') myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sprout_addr, 0)['opid'] wait_and_assert_operationid_status(self.nodes[0], myopid) print("taddr -> Sprout z_shieldcoinbase tx accepted before Canopy on node 0") @@ -59,14 +60,6 @@ def run_test (self): self.nodes[0].generate(1) self.sync_all() - # Create taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass - sendmany_tx_0 = self.nodes[0].z_sendmany(taddr_0, [{"address": self.nodes[1].z_getnewaddress('sprout'), "amount": 1}]) - wait_and_assert_operationid_status(self.nodes[0], sendmany_tx_0) - print("taddr -> Sprout z_sendmany tx accepted before Canopy on node 0") - - self.nodes[0].generate(1) - self.sync_all() - # Create mergetoaddress taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass merge_tx_0 = self.nodes[0].z_mergetoaddress(["ANY_TADDR"], self.nodes[1].z_getnewaddress('sprout')) wait_and_assert_operationid_status(self.nodes[0], merge_tx_0['opid']) @@ -75,8 +68,9 @@ def run_test (self): # Mine to one block before Canopy activation on node 0; adding value # to the Sprout pool will fail now since the transaction must be # included in the next (or later) block, after Canopy has activated. - self.nodes[0].generate(4) + self.nodes[0].generate(5) self.sync_all() + assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['e9ff75a6']['status'], 'pending') # Shield coinbase to Sprout on node 0. Should fail sprout_addr = self.nodes[0].z_getnewaddress('sprout') @@ -91,7 +85,7 @@ def run_test (self): sprout_addr = self.nodes[1].z_getnewaddress('sprout') assert_raises_message( JSONRPCException, - "Sprout shielding is not supported after Canopy", + "Sending funds into the Sprout pool is not supported by z_sendmany", self.nodes[0].z_sendmany, taddr_0, [{"address": sprout_addr, "amount": 1}]) print("taddr -> Sprout z_sendmany tx rejected at Canopy activation on node 0") @@ -109,8 +103,17 @@ def run_test (self): wait_and_assert_operationid_status(self.nodes[0], merge_tx_1['opid']) print("Sprout -> Sprout z_mergetoaddress tx accepted at Canopy activation on node 0") + # Activate Canopy self.nodes[0].generate(1) self.sync_all() + assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['e9ff75a6']['status'], 'active') + + # Generating a Sprout address should fail after Canopy. + assert_raises_message( + JSONRPCException, + "Invalid address type, \"sprout\" is not allowed after Canopy", + self.nodes[0].z_getnewaddress, 'sprout') + print("Sprout z_getnewaddress rejected at Canopy activation on node 0") # Shield coinbase to Sapling on node 0. Should pass sapling_addr = self.nodes[0].z_getnewaddress('sapling') @@ -123,7 +126,7 @@ def run_test (self): self.sync_all() # Create z_mergetoaddress Sprout -> Sprout transaction on node 1. Should pass - merge_tx_2 = self.nodes[1].z_mergetoaddress(["ANY_SPROUT"], self.nodes[2].z_getnewaddress('sprout')) + merge_tx_2 = self.nodes[1].z_mergetoaddress(["ANY_SPROUT"], sprout_addr_node2) wait_and_assert_operationid_status(self.nodes[1], merge_tx_2['opid']) print("Sprout -> Sprout z_mergetoaddress tx accepted at NU5 activation on node 1") diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 44086fa4fce..cc3659dad5d 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -29,7 +29,7 @@ def satoshi_round(amount): def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment): ''' Create and send a transaction with a random fee. - The transaction pays to a trival P2SH script, and assumes that its inputs + The transaction pays to a trivial P2SH script, and assumes that its inputs are of the same form. The function takes a list of confirmed outputs and unconfirmed outputs and attempts to use the confirmed list first for its inputs. diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 78bcf73528b..680e4a040bd 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -158,8 +158,8 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): def send_to_sprout_zaddr(self, tAddr, sproutAddr): # Send some ZEC to a Sprout address - opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) - wait_and_assert_operationid_status(self.nodes[0], opid) + result = self.nodes[0].z_shieldcoinbase(tAddr, sproutAddr, 0, 1) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) self.nodes[0].generate(1) self.sync_all() diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 6cf7d8d2b87..53a2512caae 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -4,7 +4,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . -from pyblake2 import blake2b +from hashlib import blake2b from .mininode import CBlock, CTransaction, CTxIn, CTxOut, COutPoint from .script import CScript, OP_0, OP_EQUAL, OP_HASH160, OP_TRUE, OP_CHECKSIG diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index 02d09fa203c..a09fbfe2086 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -30,6 +30,8 @@ To use, create a class that implements get_tests(), and pass it in as the test generator to TestManager. get_tests() should be a python generator that returns TestInstance objects. See below for definition. + +In practice get_tests is always implemented on a subclass of ComparisonTestFramework. ''' # TestNode behaves as follows: diff --git a/qa/rpc-tests/test_framework/flyclient.py b/qa/rpc-tests/test_framework/flyclient.py index 368c6516c52..4e01cf76c4a 100644 --- a/qa/rpc-tests/test_framework/flyclient.py +++ b/qa/rpc-tests/test_framework/flyclient.py @@ -1,4 +1,4 @@ -from pyblake2 import blake2b +from hashlib import blake2b import struct from typing import (List, Optional) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index c5f5bc1bd7f..f6421e922b0 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -36,7 +36,7 @@ from threading import Thread import logging import copy -from pyblake2 import blake2b +from hashlib import blake2b from .equihash import ( gbp_basic, @@ -52,7 +52,7 @@ OVERWINTER_PROTO_VERSION = 170003 SAPLING_PROTO_VERSION = 170006 BLOSSOM_PROTO_VERSION = 170008 -NU5_PROTO_VERSION = 170014 +NU5_PROTO_VERSION = 170015 MY_SUBVERSION = b"/python-mininode-tester:0.0.3/" @@ -374,7 +374,7 @@ def __eq__(self, other): def __repr__(self): return "CInv(type=%s hash=%064x hash_aux=%064x)" \ - % (self.typemap[self.type], self.hash, self.hash_aux) + % (self.typemap.get(self.type, self.type), self.hash, self.hash_aux) class CBlockLocator(object): @@ -660,7 +660,7 @@ def deserialize(self, f): self.encCiphertext = f.read(580) self.outCiphertext = f.read(80) self.zkproof = Groth16Proof() - self.zkproof.deserialize() + self.zkproof.deserialize(f) def serialize(self): r = b"" @@ -971,6 +971,8 @@ def __init__(self, tx=None): self.nLockTime = 0 self.nExpiryHeight = 0 self.valueBalance = 0 + self.saplingBundle = SaplingBundle() + self.orchardBundle = OrchardBundle() self.shieldedSpends = [] self.shieldedOutputs = [] self.vJoinSplit = [] @@ -988,6 +990,8 @@ def __init__(self, tx=None): self.nLockTime = tx.nLockTime self.nExpiryHeight = tx.nExpiryHeight self.valueBalance = tx.valueBalance + self.saplingBundle = copy.deepcopy(tx.saplingBundle) + self.orchardBundle = copy.deepcopy(tx.orchardBundle) self.shieldedSpends = copy.deepcopy(tx.shieldedSpends) self.shieldedOutputs = copy.deepcopy(tx.shieldedOutputs) self.vJoinSplit = copy.deepcopy(tx.vJoinSplit) @@ -1075,6 +1079,7 @@ def serialize(self): # Common transaction fields r += struct.pack("= 5: from . import zip244 txid = zip244.txid_digest(self) + self.auth_digest = zip244.auth_digest(self) else: txid = hash256(self.serialize()) + self.auth_digest = b'\xFF'*32 if self.sha256 is None: self.sha256 = uint256_from_str(txid) self.hash = encode(txid[::-1], 'hex_codec').decode('ascii') + self.auth_digest_hex = encode(self.auth_digest[::-1], 'hex_codec').decode('ascii') def is_valid(self): self.calc_sha256() @@ -1258,6 +1266,27 @@ def calc_merkle_root(self): hashes = newhashes return uint256_from_str(hashes[0]) + def calc_auth_data_root(self): + hashes = [] + nleaves = 0 + for tx in self.vtx: + tx.calc_sha256() + hashes.append(tx.auth_digest) + nleaves += 1 + # Continue adding leaves (of zeros) until reaching a power of 2 + while nleaves & (nleaves-1) > 0: + hashes.append(b'\x00'*32) + nleaves += 1 + while len(hashes) > 1: + newhashes = [] + for i in range(0, len(hashes), 2): + digest = blake2b(digest_size=32, person=b'ZcashAuthDatHash') + digest.update(hashes[i]) + digest.update(hashes[i+1]) + newhashes.append(digest.digest()) + hashes = newhashes + return hashes[0] + def is_valid(self, n=48, k=5): # H(I||... digest = blake2b(digest_size=(512//n)*n//8, person=zcash_person(n, k)) @@ -1754,6 +1783,14 @@ def serialize(self): r += ser_uint256(self.data) return r + def __eq__(self, other): + return ( + (type(self) == type(other)) and ( + (self.message, self.code, self.reason, self.data) == + (other.message, other.code, other.reason, other.data) + ) + ) + def __repr__(self): return "msg_reject: %s %d %s [%064x]" \ % (self.message, self.code, self.reason, self.data) diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index d9d548952fa..49192770da3 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -22,7 +22,7 @@ bchr = lambda x: bytes([x]) bord = lambda x: x -from pyblake2 import blake2b +from hashlib import blake2b from binascii import hexlify import struct diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 4048cf2a211..d8ba419c1bb 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -52,7 +52,7 @@ def setup_chain(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir) - def setup_network(self, split = False): + def setup_network(self, split = False, do_mempool_sync = True): self.nodes = self.setup_nodes() # Connect the nodes as a "chain". This allows us @@ -64,12 +64,13 @@ def setup_network(self, split = False): if not split: connect_nodes_bi(self.nodes, 1, 2) sync_blocks(self.nodes[1:3]) - sync_mempools(self.nodes[1:3]) + if do_mempool_sync: + sync_mempools(self.nodes[1:3]) connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 2, 3) self.is_network_split = split - self.sync_all() + self.sync_all(do_mempool_sync) def split_network(self): """ @@ -80,15 +81,17 @@ def split_network(self): wait_bitcoinds() self.setup_network(True) - def sync_all(self): + def sync_all(self, do_mempool_sync = True): if self.is_network_split: sync_blocks(self.nodes[:2]) sync_blocks(self.nodes[2:]) - sync_mempools(self.nodes[:2]) - sync_mempools(self.nodes[2:]) + if do_mempool_sync: + sync_mempools(self.nodes[:2]) + sync_mempools(self.nodes[2:]) else: sync_blocks(self.nodes) - sync_mempools(self.nodes) + if do_mempool_sync: + sync_mempools(self.nodes) def join_network(self): """ @@ -97,7 +100,7 @@ def join_network(self): assert self.is_network_split stop_nodes(self.nodes) wait_bitcoinds() - self.setup_network(False) + self.setup_network(False, False) def main(self): @@ -186,7 +189,7 @@ class ComparisonTestFramework(BitcoinTestFramework): def __init__(self): super().__init__() - self.num_nodes = 2 + self.num_nodes = 1 self.setup_clean_chain = True def add_options(self, parser): @@ -203,3 +206,6 @@ def setup_network(self): extra_args=[['-debug', '-whitelist=127.0.0.1']] * self.num_nodes, binary=[self.options.testbinary] + [self.options.refbinary]*(self.num_nodes-1)) + + def get_tests(self): + raise NotImplementedError diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index eb058b027a5..4c26ce0e669 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -40,7 +40,7 @@ BLOSSOM_BRANCH_ID = 0x2BB40E60 HEARTWOOD_BRANCH_ID = 0xF5B9230B CANOPY_BRANCH_ID = 0xE9FF75A6 -NU5_BRANCH_ID = 0xF919A198 +NU5_BRANCH_ID = 0x37519621 # The maximum number of nodes a single test can spawn MAX_NODES = 8 diff --git a/qa/rpc-tests/test_framework/zip244.py b/qa/rpc-tests/test_framework/zip244.py index 33c43e523dd..0277320533c 100644 --- a/qa/rpc-tests/test_framework/zip244.py +++ b/qa/rpc-tests/test_framework/zip244.py @@ -13,9 +13,9 @@ import struct -from pyblake2 import blake2b +from hashlib import blake2b -from .mininode import ser_uint256 +from .mininode import ser_string, ser_uint256 from .script import ( SIGHASH_ANYONECANPAY, SIGHASH_NONE, @@ -41,7 +41,7 @@ def transparent_digest(tx): def transparent_scripts_digest(tx): digest = blake2b(digest_size=32, person=b'ZTxAuthTransHash') for x in tx.vin: - digest.update(bytes(x.scriptSig)) + digest.update(ser_string(x.scriptSig)) return digest.digest() # Sapling @@ -52,7 +52,7 @@ def sapling_digest(saplingBundle): if len(saplingBundle.spends) + len(saplingBundle.outputs) > 0: digest.update(sapling_spends_digest(saplingBundle)) digest.update(sapling_outputs_digest(saplingBundle)) - digest.update(struct.pack(' 0: + # We should get an error if we generate the address at diversifier index 0. + assert_raises_message( + JSONRPCException, + 'no address at diversifier index 0', + self.nodes[0].z_getaddressforaccount, 0, [], 0) + + # The second address for account 0 is different to the first address. + addr0_2 = self.nodes[0].z_getaddressforaccount(0) + assert_equal(addr0_2['account'], 0) + assert_equal(set(addr0_2['pools']), set(['transparent', 'sapling', 'orchard'])) + ua0_2 = addr0_2['unifiedaddress'] + assert(ua0 != ua0_2) + + # We can generate a fully-shielded address. + addr0_3 = self.nodes[0].z_getaddressforaccount(0, ['sapling', 'orchard']) + assert_equal(addr0_3['account'], 0) + assert_equal(set(addr0_3['pools']), set(['sapling', 'orchard'])) + ua0_3 = addr0_3['unifiedaddress'] + + # We can generate an address without a Sapling receiver. + addr0_4 = self.nodes[0].z_getaddressforaccount(0, ['transparent', 'orchard']) + assert_equal(addr0_4['account'], 0) + assert_equal(set(addr0_4['pools']), set(['transparent', 'orchard'])) + ua0_4 = addr0_4['unifiedaddress'] + + # The first address for account 1 is different to account 0. + addr1 = self.nodes[0].z_getaddressforaccount(1) + assert_equal(addr1['account'], 1) + assert_equal(set(addr1['pools']), set(['transparent', 'sapling', 'orchard'])) + ua1 = addr1['unifiedaddress'] + assert(ua0 != ua1) + + # The UA contains the expected receiver kinds. + self.check_receiver_types(ua0, ['transparent', 'sapling', 'orchard']) + self.check_receiver_types(ua0_2, ['transparent', 'sapling', 'orchard']) + self.check_receiver_types(ua0_3, [ 'sapling', 'orchard']) + self.check_receiver_types(ua0_4, ['transparent', 'orchard']) + self.check_receiver_types(ua1, ['transparent', 'sapling', 'orchard']) + + # The balances of the accounts are all zero. + self.check_balance(0, 0, ua0, {}) + self.check_balance(0, 1, ua1, {}) + + # Send coinbase funds to the UA. + print('Sending coinbase funds to account') + recipients = [{'address': ua0, 'amount': Decimal('10')}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + txid = wait_and_assert_operationid_status(self.nodes[0], opid) + + # The wallet should detect the new note as belonging to the UA. + tx_details = self.nodes[0].z_viewtransaction(txid) + assert_equal(len(tx_details['outputs']), 1) + assert_equal(tx_details['outputs'][0]['type'], 'sapling') + assert_equal(tx_details['outputs'][0]['address'], ua0) + + # The new balance should not be visible with the default minconf, but should be + # visible with minconf=0. + self.sync_all() + self.check_balance(0, 0, ua0, {}) + self.check_balance(0, 0, ua0, {'sapling': 10}, 0) + + self.nodes[2].generate(1) + self.sync_all() + + # The default minconf should now detect the balance. + self.check_balance(0, 0, ua0, {'sapling': 10}) + + # Send Sapling funds from the UA. + print('Sending account funds to Sapling address') + node1sapling = self.nodes[1].z_getnewaddress('sapling') + recipients = [{'address': node1sapling, 'amount': Decimal('1')}] + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + txid = wait_and_assert_operationid_status(self.nodes[0], opid) + + # The wallet should detect the spent note as belonging to the UA. + tx_details = self.nodes[0].z_viewtransaction(txid) + assert_equal(len(tx_details['spends']), 1) + assert_equal(tx_details['spends'][0]['type'], 'sapling') + assert_equal(tx_details['spends'][0]['address'], ua0) + + # The balances of the account should reflect whether zero-conf transactions are + # being considered. We will show either 0 (because the spent 10-ZEC note is never + # shown, as that transaction has been created and broadcast, and _might_ get mined + # up until the transaction expires), or 9 (if we include the unmined transaction). + self.sync_all() + self.check_balance(0, 0, ua0, {}) + self.check_balance(0, 0, ua0, {'sapling': 9}, 0) + + # Activate NU5 + print('Activating NU5') + self.nodes[2].generate(9) + self.sync_all() + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 210) + + # Send more coinbase funds to the UA. + print('Sending coinbase funds to account') + recipients = [{'address': ua0, 'amount': Decimal('10')}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + txid = wait_and_assert_operationid_status(self.nodes[0], opid) + + # The wallet should detect the new note as belonging to the UA. + tx_details = self.nodes[0].z_viewtransaction(txid) + assert_equal(len(tx_details['outputs']), 1) + assert_equal(tx_details['outputs'][0]['type'], 'orchard') + assert_equal(tx_details['outputs'][0]['address'], ua0) + + # The new balance should not be visible with the default minconf, but should be + # visible with minconf=0. + self.sync_all() + self.check_balance(0, 0, ua0, {'sapling': 9}) + self.check_balance(0, 0, ua0, {'sapling': 9, 'orchard': 10}, 0) + + # The total balance with the default minconf should be just the Sapling balance + assert_equal('9.00', self.nodes[0].z_gettotalbalance()['private']) + assert_equal('19.00', self.nodes[0].z_gettotalbalance(0)['private']) + + self.nodes[2].generate(1) + self.sync_all() + + # Send Orchard funds from the UA. + print('Sending account funds to Orchard-only UA') + node1account = self.nodes[1].z_getnewaccount()['account'] + node1orchard = self.nodes[1].z_getaddressforaccount(node1account, ['orchard'])['unifiedaddress'] + recipients = [{'address': node1orchard, 'amount': Decimal('1')}] + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + txid = wait_and_assert_operationid_status(self.nodes[0], opid) + + # The wallet should detect the spent note as belonging to the UA. + # TODO ORCHARD: Uncomment this once z_viewtransaction shows Orchard details (#5186). + # tx_details = self.nodes[0].z_viewtransaction(txid) + # assert_equal(len(tx_details['spends']), 1) + # assert_equal(tx_details['spends'][0]['type'], 'orchard') + # assert_equal(tx_details['spends'][0]['address'], ua0) + # assert_equal(len(tx_details['outputs']), 1) + # assert_equal(tx_details['outputs'][0]['type'], 'orchard') + # assert_equal(tx_details['outputs'][0]['address'], ua0) + + # The balances of the account should reflect whether zero-conf transactions are + # being considered. The Sapling balance should remain at 9, while the Orchard + # balance will show either 0 (because the spent 10-ZEC note is never shown, as + # that transaction has been created and broadcast, and _might_ get mined up until + # the transaction expires), or 9 (if we include the unmined transaction). + self.sync_all() + self.check_balance(0, 0, ua0, {'sapling': 9}) + self.check_balance(0, 0, ua0, {'sapling': 9, 'orchard': 9}, 0) + + +if __name__ == '__main__': + WalletAccountsTest().main() diff --git a/qa/rpc-tests/wallet_addresses.py b/qa/rpc-tests/wallet_addresses.py index d70b1bca06a..aa282ea7735 100755 --- a/qa/rpc-tests/wallet_addresses.py +++ b/qa/rpc-tests/wallet_addresses.py @@ -27,6 +27,15 @@ def addr_checks(default_type): assert_equal(res['type'], addr_type) assert(addr in all_addresses) + listed_addresses = self.nodes[0].listaddresses() + legacy_random_src = next(src for src in listed_addresses if src['source'] == 'legacy_random') + legacy_hdseed_src = next(src for src in listed_addresses if src['source'] == 'legacy_hdseed') + for addr_type, addr in types_and_addresses: + if addr_type == 'sprout': + assert(addr in legacy_random_src['sprout']['addresses']) + if addr_type == 'sapling': + assert(addr in [x for obj in legacy_hdseed_src['sapling'] for x in obj['addresses']]) + # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) diff --git a/qa/rpc-tests/wallet_broadcast.py b/qa/rpc-tests/wallet_broadcast.py index f0cebe355fa..f625c8aacdb 100755 --- a/qa/rpc-tests/wallet_broadcast.py +++ b/qa/rpc-tests/wallet_broadcast.py @@ -13,7 +13,7 @@ def run_test(self): #do some -walletbroadcast tests stop_nodes(self.nodes) wait_bitcoinds() - self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) + self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"]] * 3) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py index 4e3dbf17ea1..409e2b94e8b 100755 --- a/qa/rpc-tests/wallet_changeaddresses.py +++ b/qa/rpc-tests/wallet_changeaddresses.py @@ -81,15 +81,11 @@ def check_change_taddr_reuse(target): taddr = self.nodes[0].getnewaddress() saplingAddr = self.nodes[0].z_getnewaddress('sapling') - sproutAddr = self.nodes[0].z_getnewaddress('sprout') print() print('Checking z_sendmany(taddr->Sapling)') check_change_taddr_reuse(saplingAddr) print() - print('Checking z_sendmany(taddr->Sprout)') - check_change_taddr_reuse(sproutAddr) - print() print('Checking z_sendmany(taddr->taddr)') check_change_taddr_reuse(taddr) diff --git a/qa/rpc-tests/wallet_import_export.py b/qa/rpc-tests/wallet_import_export.py index 67e43842c6d..b5d091ac3c1 100755 --- a/qa/rpc-tests/wallet_import_export.py +++ b/qa/rpc-tests/wallet_import_export.py @@ -3,13 +3,16 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_true, start_nodes class WalletImportExportTest (BitcoinTestFramework): def setup_network(self, split=False): num_nodes = 3 - extra_args = [["-exportdir={}/export{}".format(self.options.tmpdir, i)] for i in range(num_nodes)] + extra_args = [([ + "-exportdir={}/export{}".format(self.options.tmpdir, i), + ] + (["-walletrequirebackup"] if i == 0 else [])) for i in range(num_nodes)] self.nodes = start_nodes(num_nodes, self.options.tmpdir, extra_args) def run_test(self): @@ -17,12 +20,28 @@ def run_test(self): privkey2 = self.nodes[2].z_exportkey(sapling_address2) self.nodes[0].z_importkey(privkey2) + # test walletconfirmbackup + try: + self.nodes[0].getnewaddress() + except JSONRPCException as e: + errorString = e.error['message'] + assert_equal("Error: Please acknowledge that you have backed up" in errorString, True) + try: + self.nodes[0].z_getnewaddress('sapling') + except JSONRPCException as e: + errorString = e.error['message'] + assert_equal("Error: Please acknowledge that you have backed up" in errorString, True) + dump_path0 = self.nodes[0].z_exportwallet('walletdumpmnem') + (mnemonic, _, _, _) = parse_wallet_file(dump_path0) + self.nodes[0].walletconfirmbackup(mnemonic) + + # Now that we've confirmed backup, we can generate addresses sprout_address0 = self.nodes[0].z_getnewaddress('sprout') sapling_address0 = self.nodes[0].z_getnewaddress('sapling') # node 0 should have the keys dump_path0 = self.nodes[0].z_exportwallet('walletdump') - (t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0) + (_, t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0) sapling_line_lengths = [len(sapling_key0.split(' #')[0].split()) for sapling_key0 in sapling_keys0.splitlines()] assert_equal(2, len(sapling_line_lengths), "Should have 2 sapling keys") @@ -35,7 +54,7 @@ def run_test(self): # node 1 should not have the keys dump_path1 = self.nodes[1].z_exportwallet('walletdumpbefore') - (t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) + (_, t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) assert_true(sprout_address0 not in sprout_keys1) assert_true(sapling_address0 not in sapling_keys1) @@ -45,13 +64,13 @@ def run_test(self): # node 1 should now have the keys dump_path1 = self.nodes[1].z_exportwallet('walletdumpafter') - (t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) + (_, t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) assert_true(sprout_address0 in sprout_keys1) assert_true(sapling_address0 in sapling_keys1) assert_true(sapling_address2 in sapling_keys1) - # make sure we have perserved the metadata + # make sure we have preserved the metadata for sapling_key0 in sapling_keys0.splitlines(): assert_true(sapling_key0 in sapling_keys1) @@ -59,15 +78,15 @@ def run_test(self): def parse_wallet_file(dump_path): file_lines = open(dump_path, "r", encoding="utf8").readlines() # We expect information about the HDSeed and fingerpring in the header - assert_true("HDSeed" in file_lines[4], "Expected HDSeed") - assert_true("fingerprint" in file_lines[4], "Expected fingerprint") - seed_comment_line = file_lines[4][2:].split() # ["HDSeed=...", "fingerprint=..."] - assert_true(seed_comment_line[0].split("=")[1] != seed_comment_line[1].split("=")[1], "The seed should not equal the fingerprint") + assert_true("recovery_phrase" in file_lines[5], "Expected emergency recovery phrase") + assert_true("language" in file_lines[6], "Expected mnemonic seed language") + assert_true("fingerprint" in file_lines[7], "Expected mnemonic seed fingerprint") + mnemonic = file_lines[5].split("=")[1].replace("\"", "").strip() (t_keys, i) = parse_wallet_file_lines(file_lines, 0) (sprout_keys, i) = parse_wallet_file_lines(file_lines, i) (sapling_keys, i) = parse_wallet_file_lines(file_lines, i) - return (t_keys, sprout_keys, sapling_keys) + return (mnemonic, t_keys, sprout_keys, sapling_keys) def parse_wallet_file_lines(file_lines, i): keys = [] @@ -81,4 +100,4 @@ def parse_wallet_file_lines(file_lines, i): return ("".join(keys), i) if __name__ == '__main__': - WalletImportExportTest().main() \ No newline at end of file + WalletImportExportTest().main() diff --git a/qa/rpc-tests/wallet_isfromme.py b/qa/rpc-tests/wallet_isfromme.py new file mode 100755 index 00000000000..aefef06771c --- /dev/null +++ b/qa/rpc-tests/wallet_isfromme.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + BLOSSOM_BRANCH_ID, + CANOPY_BRANCH_ID, + HEARTWOOD_BRANCH_ID, + OVERWINTER_BRANCH_ID, + SAPLING_BRANCH_ID, + assert_equal, + get_coinbase_address, + initialize_chain_clean, + nuparams, + start_nodes, + wait_and_assert_operationid_status, +) + +from decimal import Decimal + +class WalletIsFromMe(BitcoinTestFramework): + def setup_chain(self): + initialize_chain_clean(self.options.tmpdir, 1) + + def setup_network(self, split=False): + self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[[ + nuparams(OVERWINTER_BRANCH_ID, 1), + nuparams(SAPLING_BRANCH_ID, 1), + nuparams(BLOSSOM_BRANCH_ID, 1), + nuparams(HEARTWOOD_BRANCH_ID, 1), + nuparams(CANOPY_BRANCH_ID, 1), + ]]) + self.is_network_split=False + + def run_test (self): + node = self.nodes[0] + + node.generate(101) + assert_equal(node.getbalance('', 0), Decimal('6.25')) + + coinbase_addr = get_coinbase_address(node) + + # Send all available funds to a z-address. + zaddr = node.z_getnewaddress() + wait_and_assert_operationid_status( + node, + node.z_sendmany( + coinbase_addr, + [ + {'address': zaddr, 'amount': Decimal('6.25')}, + ], + 0, + 0, + ), + ) + self.sync_all() + assert_equal(node.getbalance('', 0), 0) + + # Mine the transaction; we get another coinbase output. + self.nodes[0].generate(1) + self.sync_all() + assert_equal(node.getbalance('', 0), Decimal('6.25')) + + # Now send the funds back to a new t-address. + taddr = node.getnewaddress() + wait_and_assert_operationid_status( + node, + node.z_sendmany( + zaddr, + [ + {'address': taddr, 'amount': Decimal('6.25')}, + ], + 1, + 0, + ), + ) + self.sync_all() + + # At this point we have created the conditions for the bug in + # https://github.com/zcash/zcash/issues/5325. + + # listunspent should show the coinbase output, and optionally the + # newly-received unshielding output. + assert_equal(len(node.listunspent()), 1) + assert_equal(len(node.listunspent(0)), 2) + + # "getbalance '' 0" should count both outputs. The bug failed here. + assert_equal(node.getbalance('', 0), Decimal('12.5')) + +if __name__ == '__main__': + WalletIsFromMe().main () diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index bdfb6ccad94..1986467454e 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -6,7 +6,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - get_coinbase_address, wait_and_assert_operationid_status, DEFAULT_FEE ) @@ -20,7 +19,6 @@ def run_test(self): # Current height = 200 assert_equal(200, self.nodes[0].getblockcount()) sproutzaddr = self.nodes[0].z_getnewaddress('sprout') - saplingzaddr = self.nodes[0].z_getnewaddress('sapling') # we've got lots of coinbase (taddr) but no shielded funds yet assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) @@ -30,11 +28,10 @@ def run_test(self): self.sync_all() assert_equal(201, self.nodes[0].getblockcount()) - # Shield coinbase funds (must be a multiple of 10, no change allowed) - receive_amount_10 = Decimal('10.0') - DEFAULT_FEE - recipients = [{"address":sproutzaddr, "amount":receive_amount_10}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients) - txid_1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + # Shield one coinbase output + receive_amount_1 = Decimal('10.0') - DEFAULT_FEE + result = self.nodes[0].z_shieldcoinbase('*', sproutzaddr, DEFAULT_FEE, 1) + txid_1 = wait_and_assert_operationid_status(self.nodes[0], result['opid']) self.sync_all() # No funds (with (default) one or more confirmations) in sproutzaddr yet @@ -49,9 +46,10 @@ def run_test(self): assert_equal(1, len(unspent_cb)) assert_equal(False, unspent_cb[0]['change']) assert_equal(txid_1, unspent_cb[0]['txid']) + assert_equal('sprout', unspent_cb[0]['type']) assert_equal(True, unspent_cb[0]['spendable']) assert_equal(sproutzaddr, unspent_cb[0]['address']) - assert_equal(receive_amount_10, unspent_cb[0]['amount']) + assert_equal(receive_amount_1, unspent_cb[0]['amount']) # list unspent, filtering by address, should produce same result unspent_cb_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) @@ -64,13 +62,13 @@ def run_test(self): # Current height = 202 assert_equal(202, self.nodes[0].getblockcount()) - # Send 1.0 minus default fee from sproutzaddr to a new zaddr - sproutzaddr2 = self.nodes[0].z_getnewaddress('sprout') - receive_amount_1 = Decimal('1.0') - DEFAULT_FEE - change_amount_9 = receive_amount_10 - Decimal('1.0') - assert_equal('sprout', self.nodes[0].z_validateaddress(sproutzaddr2)['type']) - recipients = [{"address": sproutzaddr2, "amount":receive_amount_1}] - myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients) + # Send 1.0 minus default fee from sproutzaddr to a new Sapling zaddr + saplingzaddr = self.nodes[0].z_getnewaddress('sapling') + receive_amount_2 = Decimal('1.0') + change_amount_2 = receive_amount_1 - receive_amount_2 - DEFAULT_FEE + assert_equal('sapling', self.nodes[0].z_validateaddress(saplingzaddr)['type']) + recipients = [{"address": saplingzaddr, "amount":receive_amount_2}] + myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE) txid_2 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -81,17 +79,19 @@ def run_test(self): unspent_tx = sorted(unspent_tx, key=lambda k: k['amount']) assert_equal(False, unspent_tx[0]['change']) assert_equal(txid_2, unspent_tx[0]['txid']) + assert_equal('sapling', unspent_tx[0]['type']) assert_equal(True, unspent_tx[0]['spendable']) - assert_equal(sproutzaddr2, unspent_tx[0]['address']) - assert_equal(receive_amount_1, unspent_tx[0]['amount']) + assert_equal(saplingzaddr, unspent_tx[0]['address']) + assert_equal(receive_amount_2, unspent_tx[0]['amount']) assert_equal(True, unspent_tx[1]['change']) assert_equal(txid_2, unspent_tx[1]['txid']) + assert_equal('sprout', unspent_tx[1]['type']) assert_equal(True, unspent_tx[1]['spendable']) assert_equal(sproutzaddr, unspent_tx[1]['address']) - assert_equal(change_amount_9, unspent_tx[1]['amount']) + assert_equal(change_amount_2, unspent_tx[1]['amount']) - unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr2]) + unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]) assert_equal(1, len(unspent_tx_filter)) assert_equal(unspent_tx[0], unspent_tx_filter[0]) @@ -99,15 +99,15 @@ def run_test(self): assert_equal(1, len(unspent_tx_filter)) assert_equal(unspent_tx[1], unspent_tx_filter[0]) - # No funds in saplingzaddr yet - assert_equal(0, len(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]))) + self.nodes[0].generate(1) + self.sync_all() - # Send 2.0 minus default fee to our sapling zaddr - # (sending from a sprout zaddr to a sapling zaddr is disallowed, - # so send from coin base) - receive_amount_2 = Decimal('2.0') - DEFAULT_FEE - recipients = [{"address": saplingzaddr, "amount":receive_amount_2}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients) + # Send 2.0 minus default fee to a new sapling zaddr + saplingzaddr2 = self.nodes[0].z_getnewaddress('sapling') + receive_amount_3 = Decimal('2.0') + change_amount_3 = change_amount_2 - receive_amount_3 - DEFAULT_FEE + recipients = [{"address": saplingzaddr2, "amount":receive_amount_3}] + myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE) txid_3 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() unspent_tx = self.nodes[0].z_listunspent(0) @@ -118,32 +118,35 @@ def run_test(self): assert_equal(False, unspent_tx[0]['change']) assert_equal(txid_2, unspent_tx[0]['txid']) + assert_equal('sapling', unspent_tx[0]['type']) assert_equal(True, unspent_tx[0]['spendable']) - assert_equal(sproutzaddr2, unspent_tx[0]['address']) - assert_equal(receive_amount_1, unspent_tx[0]['amount']) + assert_equal(saplingzaddr, unspent_tx[0]['address']) + assert_equal(receive_amount_2, unspent_tx[0]['amount']) assert_equal(False, unspent_tx[1]['change']) assert_equal(txid_3, unspent_tx[1]['txid']) + assert_equal('sapling', unspent_tx[1]['type']) assert_equal(True, unspent_tx[1]['spendable']) - assert_equal(saplingzaddr, unspent_tx[1]['address']) - assert_equal(receive_amount_2, unspent_tx[1]['amount']) + assert_equal(saplingzaddr2, unspent_tx[1]['address']) + assert_equal(receive_amount_3, unspent_tx[1]['amount']) assert_equal(True, unspent_tx[2]['change']) - assert_equal(txid_2, unspent_tx[2]['txid']) + assert_equal(txid_3, unspent_tx[2]['txid']) + assert_equal('sprout', unspent_tx[2]['type']) assert_equal(True, unspent_tx[2]['spendable']) assert_equal(sproutzaddr, unspent_tx[2]['address']) - assert_equal(change_amount_9, unspent_tx[2]['amount']) + assert_equal(change_amount_3, unspent_tx[2]['amount']) unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]) assert_equal(1, len(unspent_tx_filter)) - assert_equal(unspent_tx[1], unspent_tx_filter[0]) + assert_equal(unspent_tx[0], unspent_tx_filter[0]) # test that pre- and post-sapling can be filtered in a single call unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr, saplingzaddr]) assert_equal(2, len(unspent_tx_filter)) unspent_tx_filter = sorted(unspent_tx_filter, key=lambda k: k['amount']) - assert_equal(unspent_tx[1], unspent_tx_filter[0]) + assert_equal(unspent_tx[0], unspent_tx_filter[0]) assert_equal(unspent_tx[2], unspent_tx_filter[1]) # so far, this node has no watchonly addresses, so results are the same diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index d63053bc32f..e85869485a9 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -3,9 +3,21 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_true, assert_false, DEFAULT_FEE, DEFAULT_FEE_ZATS -from test_framework.util import wait_and_assert_operationid_status +from test_framework.util import ( + assert_equal, + assert_true, + assert_false, + assert_raises_message, + connect_nodes_bi, + get_coinbase_address, + nuparams, + DEFAULT_FEE, + DEFAULT_FEE_ZATS, + NU5_BRANCH_ID, +) +from test_framework.util import wait_and_assert_operationid_status, start_nodes from decimal import Decimal my_memo_str = 'c0ffee' # stay awake @@ -15,21 +27,195 @@ no_memo = 'f6' + ('0'*1022) # see section 5.5 of the protocol spec class ListReceivedTest (BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = True + + def setup_network(self): + self.nodes = start_nodes( + self.num_nodes, self.options.tmpdir, + extra_args=[[ + '-experimentalfeatures', + '-orchardwallet', + nuparams(NU5_BRANCH_ID, 225), + ]] * self.num_nodes + ) + connect_nodes_bi(self.nodes, 0, 1) + connect_nodes_bi(self.nodes, 1, 2) + connect_nodes_bi(self.nodes, 0, 2) + self.is_network_split = False + self.sync_all() def generate_and_sync(self, new_height): current_height = self.nodes[0].getblockcount() assert(new_height > current_height) + self.sync_all() self.nodes[0].generate(new_height - current_height) self.sync_all() assert_equal(new_height, self.nodes[0].getblockcount()) - def run_test_release(self, release, height): + def test_received_sprout(self, height): + self.generate_and_sync(height+2) + + zaddr1 = self.nodes[1].z_getnewaddress('sprout') + + # Send 10 ZEC each zaddr1 and zaddrExt via z_shieldcoinbase + result = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), zaddr1, 0, 1) + txid_shielding1 = wait_and_assert_operationid_status(self.nodes[0], result['opid']) + + zaddrExt = self.nodes[2].z_getnewaddress('sprout') + result = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), zaddrExt, 0, 1) + txid_shieldingExt = wait_and_assert_operationid_status(self.nodes[0], result['opid']) + + self.sync_all() + + # Decrypted transaction details should not be visible on node 0 + pt = self.nodes[0].z_viewtransaction(txid_shielding1) + assert_equal(pt['txid'], txid_shielding1) + assert_equal(len(pt['spends']), 0) + assert_equal(len(pt['outputs']), 0) + + # Decrypted transaction details should be correct on node 1 + pt = self.nodes[1].z_viewtransaction(txid_shielding1) + assert_equal(pt['txid'], txid_shielding1) + assert_equal(len(pt['spends']), 0) + assert_equal(len(pt['outputs']), 1) + assert_equal(pt['outputs'][0]['type'], 'sprout') + assert_equal(pt['outputs'][0]['js'], 0) + assert_equal(pt['outputs'][0]['address'], zaddr1) + assert_equal(pt['outputs'][0]['value'], Decimal('10')) + assert_equal(pt['outputs'][0]['valueZat'], 1000000000) + assert_equal(pt['outputs'][0]['memo'], no_memo) + jsOutputPrev = pt['outputs'][0]['jsOutput'] + + # Second transaction should not be known to node 1 + assert_raises_message( + JSONRPCException, + "Invalid or non-wallet transaction id", + self.nodes[1].z_viewtransaction, + txid_shieldingExt) + + # Second transaction should be visible on node0 + pt = self.nodes[2].z_viewtransaction(txid_shieldingExt) + assert_equal(pt['txid'], txid_shieldingExt) + assert_equal(len(pt['spends']), 0) + assert_equal(len(pt['outputs']), 1) + assert_equal(pt['outputs'][0]['type'], 'sprout') + assert_equal(pt['outputs'][0]['js'], 0) + assert_equal(pt['outputs'][0]['address'], zaddrExt) + assert_equal(pt['outputs'][0]['value'], Decimal('10')) + assert_equal(pt['outputs'][0]['valueZat'], 1000000000) + assert_equal(pt['outputs'][0]['memo'], no_memo) + + r = self.nodes[1].z_listreceivedbyaddress(zaddr1) + assert_equal(0, len(r), "Should have received no confirmed note") + c = self.nodes[1].z_getnotescount() + assert_equal(0, c['sprout'], "Count of confirmed notes should be 0") + + # No confirmation required, one note should be present + r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) + assert_equal(1, len(r), "Should have received one (unconfirmed) note") + assert_equal(txid_shielding1, r[0]['txid']) + assert_equal(10, r[0]['amount']) + assert_equal(1000000000, r[0]['amountZat']) + assert_false(r[0]['change'], "Note should not be change") + assert_equal(no_memo, r[0]['memo']) + assert_equal(0, r[0]['confirmations']) + assert_equal(-1, r[0]['blockindex']) + assert_equal(0, r[0]['blockheight']) + + c = self.nodes[1].z_getnotescount(0) + assert_equal(1, c['sprout'], "Count of unconfirmed notes should be 1") + + # Confirm transaction (10 ZEC shielded) + self.generate_and_sync(height+3) + + # Require one confirmation, note should be present + r0 = self.nodes[1].z_listreceivedbyaddress(zaddr1) + assert_equal(1, len(r0), "Should have received one (unconfirmed) note") + assert_equal(txid_shielding1, r0[0]['txid']) + assert_equal(10, r0[0]['amount']) + assert_equal(1000000000, r0[0]['amountZat']) + assert_false(r0[0]['change'], "Note should not be change") + assert_equal(no_memo, r0[0]['memo']) + assert_equal(1, r0[0]['confirmations']) + assert_equal(height + 3, r0[0]['blockheight']) + + taddr = self.nodes[1].getnewaddress() + # Generate some change by sending part of zaddr1 back to taddr + opid = self.nodes[1].z_sendmany(zaddr1, [{'address': taddr, 'amount': 0.6}]) + txid = wait_and_assert_operationid_status(self.nodes[1], opid) + + self.generate_and_sync(height+4) + + # Decrypted transaction details should be correct + pt = self.nodes[1].z_viewtransaction(txid) + assert_equal(pt['txid'], txid) + assert_equal(len(pt['spends']), 1) + # TODO: enable once z_viewtransaction displays transparent elements + # assert_equal(len(pt['outputs']), 2) + assert_equal(len(pt['outputs']), 1) + + assert_equal(pt['spends'][0]['type'], 'sprout') + assert_equal(pt['spends'][0]['txidPrev'], txid_shielding1) + assert_equal(pt['spends'][0]['js'], 0) + assert_equal(pt['spends'][0]['jsPrev'], 0) + assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev) + assert_equal(pt['spends'][0]['address'], zaddr1) + assert_equal(pt['spends'][0]['value'], Decimal('10.0')) + assert_equal(pt['spends'][0]['valueZat'], 1000000000) + + # We expect a transparent output and a Sprout output, but the RPC does + # not define any particular ordering of these within the returned JSON. + outputs = [{ + 'type': output['type'], + 'address': output['address'], + 'value': output['value'], + 'valueZat': output['valueZat'], + } for output in pt['outputs']] + for (i, output) in enumerate(pt['outputs']): + if 'memo' in output: + outputs[i]['memo'] = output['memo'] + + # TODO: enable once z_viewtransaction displays transparent elements + # assert({ + # 'type': 'transparent', + # 'address': taddr, + # 'value': Decimal('0.6'), + # 'valueZat': 60000000, + # } in outputs) + assert({ + 'type': 'sprout', + 'address': zaddr1, + 'value': Decimal('9.4') - DEFAULT_FEE, + 'valueZat': 940000000 - DEFAULT_FEE_ZATS, + 'memo': no_memo, + } in outputs) + + # zaddr1 should have a note with change + r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) + assert_equal(2, len(r), "zaddr1 Should have received 2 notes") + r = sorted(r, key = lambda received: received['amount']) + assert_equal(txid, r[0]['txid']) + assert_equal(Decimal('9.4')-DEFAULT_FEE, r[0]['amount']) + assert_equal(940000000-DEFAULT_FEE_ZATS, r[0]['amountZat']) + assert_true(r[0]['change'], "Note valued at (9.4-"+str(DEFAULT_FEE)+") should be change") + assert_equal(no_memo, r[0]['memo']) + + # The old note still exists (it's immutable), even though it is spent + assert_equal(Decimal('10.0'), r[1]['amount']) + assert_equal(1000000000, r[1]['amountZat']) + assert_false(r[1]['change'], "Note valued at 10.0 should not be change") + assert_equal(no_memo, r[1]['memo']) + + def test_received_sapling(self, height): self.generate_and_sync(height+1) taddr = self.nodes[1].getnewaddress() - zaddr1 = self.nodes[1].z_getnewaddress(release) - zaddrExt = self.nodes[3].z_getnewaddress(release) + zaddr1 = self.nodes[1].z_getnewaddress('sapling') + zaddrExt = self.nodes[2].z_getnewaddress('sapling') - self.nodes[0].sendtoaddress(taddr, 4.0) + txid_taddr = self.nodes[0].sendtoaddress(taddr, 4.0) self.generate_and_sync(height+2) # Send 1 ZEC to zaddr1 @@ -42,62 +228,35 @@ def run_test_release(self, release, height): # Decrypted transaction details should be correct pt = self.nodes[1].z_viewtransaction(txid) + assert_equal(pt['txid'], txid) assert_equal(len(pt['spends']), 0) - assert_equal(len(pt['outputs']), 1 if release == 'sprout' else 2) - - # Output orders can be randomized, so we check the output - # positions and contents separately - outputs = [] - - assert_equal(pt['outputs'][0]['type'], release) - if release == 'sprout': - assert_equal(pt['outputs'][0]['js'], 0) - jsOutputPrev = pt['outputs'][0]['jsOutput'] - elif pt['outputs'][0]['address'] == zaddr1: - assert_equal(pt['outputs'][0]['outgoing'], False) - assert_equal(pt['outputs'][0]['memoStr'], my_memo_str) - else: - assert_equal(pt['outputs'][0]['outgoing'], True) - outputs.append({ - 'address': pt['outputs'][0]['address'], - 'value': pt['outputs'][0]['value'], - 'valueZat': pt['outputs'][0]['valueZat'], - 'memo': pt['outputs'][0]['memo'], - }) - - if release != 'sprout': - assert_equal(pt['outputs'][1]['type'], release) - if pt['outputs'][1]['address'] == zaddr1: - assert_equal(pt['outputs'][1]['outgoing'], False) - assert_equal(pt['outputs'][1]['memoStr'], my_memo_str) - else: - assert_equal(pt['outputs'][1]['outgoing'], True) - outputs.append({ - 'address': pt['outputs'][1]['address'], - 'value': pt['outputs'][1]['value'], - 'valueZat': pt['outputs'][1]['valueZat'], - 'memo': pt['outputs'][1]['memo'], - }) + assert_equal(len(pt['outputs']), 2) - assert({ - 'address': zaddr1, - 'value': Decimal('1'), - 'valueZat': 100000000, - 'memo': my_memo, - } in outputs) - if release != 'sprout': - assert({ - 'address': zaddrExt, - 'value': Decimal('2'), - 'valueZat': 200000000, - 'memo': no_memo, - } in outputs) + # Outputs are not returned in a defined order but the amounts are deterministic + outputs = sorted(pt['outputs'], key=lambda x: x['valueZat']) + assert_equal(outputs[0]['type'], 'sapling') + assert_equal(outputs[0]['address'], zaddr1) + assert_equal(outputs[0]['value'], Decimal('1')) + assert_equal(outputs[0]['valueZat'], 100000000) + assert_equal(outputs[0]['output'], 0) + assert_equal(outputs[0]['outgoing'], False) + assert_equal(outputs[0]['memo'], my_memo) + assert_equal(outputs[0]['memoStr'], my_memo_str) + + assert_equal(outputs[1]['type'], 'sapling') + assert_equal(outputs[1]['address'], zaddrExt) + assert_equal(outputs[1]['value'], Decimal('2')) + assert_equal(outputs[1]['valueZat'], 200000000) + assert_equal(outputs[1]['output'], 1) + assert_equal(outputs[1]['outgoing'], True) + assert_equal(outputs[1]['memo'], no_memo) + assert 'memoStr' not in outputs[1] r = self.nodes[1].z_listreceivedbyaddress(zaddr1) assert_equal(0, len(r), "Should have received no confirmed note") c = self.nodes[1].z_getnotescount() - assert_equal(0, c[release], "Count of confirmed notes should be 0") + assert_equal(0, c['sapling'], "Count of confirmed notes should be 0") # No confirmation required, one note should be present r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) @@ -112,7 +271,7 @@ def run_test_release(self, release, height): assert_equal(0, r[0]['blockheight']) c = self.nodes[1].z_getnotescount(0) - assert_equal(1, c[release], "Count of unconfirmed notes should be 1") + assert_equal(1, c['sapling'], "Count of unconfirmed notes should be 1") # Confirm transaction (1 ZEC from taddr to zaddr1) self.generate_and_sync(height+3) @@ -129,7 +288,7 @@ def run_test_release(self, release, height): # Generate some change by sending part of zaddr1 to zaddr2 txidPrev = txid - zaddr2 = self.nodes[1].z_getnewaddress(release) + zaddr2 = self.nodes[1].z_getnewaddress('sapling') opid = self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6}]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) @@ -142,92 +301,259 @@ def run_test_release(self, release, height): assert_equal(len(pt['spends']), 1) assert_equal(len(pt['outputs']), 2) - assert_equal(pt['spends'][0]['type'], release) + assert_equal(pt['spends'][0]['type'], 'sapling') assert_equal(pt['spends'][0]['txidPrev'], txidPrev) - if release == 'sprout': - assert_equal(pt['spends'][0]['js'], 0) - # jsSpend is randomised during transaction creation - assert_equal(pt['spends'][0]['jsPrev'], 0) - assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev) - else: - assert_equal(pt['spends'][0]['spend'], 0) - assert_equal(pt['spends'][0]['outputPrev'], 0) + assert_equal(pt['spends'][0]['spend'], 0) + assert_equal(pt['spends'][0]['outputPrev'], 0) assert_equal(pt['spends'][0]['address'], zaddr1) assert_equal(pt['spends'][0]['value'], Decimal('1.0')) assert_equal(pt['spends'][0]['valueZat'], 100000000) - # Output orders can be randomized, so we check the output - # positions and contents separately - outputs = [] - - assert_equal(pt['outputs'][0]['type'], release) - if release == 'sapling': - assert_equal(pt['outputs'][0]['output'], 0) - assert_equal(pt['outputs'][0]['outgoing'], False) - outputs.append({ - 'address': pt['outputs'][0]['address'], - 'value': pt['outputs'][0]['value'], - 'valueZat': pt['outputs'][0]['valueZat'], - 'memo': pt['outputs'][0]['memo'], - }) - - assert_equal(pt['outputs'][1]['type'], release) - if release == 'sapling': - assert_equal(pt['outputs'][1]['output'], 1) - assert_equal(pt['outputs'][1]['outgoing'], False) - outputs.append({ - 'address': pt['outputs'][1]['address'], - 'value': pt['outputs'][1]['value'], - 'valueZat': pt['outputs'][1]['valueZat'], - 'memo': pt['outputs'][1]['memo'], - }) - - assert({ - 'address': zaddr2, - 'value': Decimal('0.6'), - 'valueZat': 60000000, - 'memo': no_memo, - } in outputs) - assert({ - 'address': zaddr1, - 'value': Decimal('0.4') - DEFAULT_FEE, - 'valueZat': 40000000 - DEFAULT_FEE_ZATS, - 'memo': no_memo, - } in outputs) + # Outputs are not returned in a defined order but the amounts are deterministic + outputs = sorted(pt['outputs'], key=lambda x: x['valueZat']) + assert_equal(outputs[0]['type'], 'sapling') + assert_equal(outputs[0]['address'], zaddr1) + assert_equal(outputs[0]['value'], Decimal('0.4') - DEFAULT_FEE) + assert_equal(outputs[0]['valueZat'], 40000000 - DEFAULT_FEE_ZATS) + assert_equal(outputs[0]['output'], 1) + assert_equal(outputs[0]['outgoing'], False) + assert_equal(outputs[0]['memo'], no_memo) + assert 'memoStr' not in outputs[0] + + assert_equal(outputs[1]['type'], 'sapling') + assert_equal(outputs[1]['address'], zaddr2) + assert_equal(outputs[1]['value'], Decimal('0.6')) + assert_equal(outputs[1]['valueZat'], 60000000) + assert_equal(outputs[1]['output'], 0) + assert_equal(outputs[1]['outgoing'], False) + assert_equal(outputs[1]['memo'], no_memo) + assert 'memoStr' not in outputs[1] # zaddr1 should have a note with change r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) - r = sorted(r, key = lambda received: received['amount']) assert_equal(2, len(r), "zaddr1 Should have received 2 notes") - + r = sorted(r, key = lambda received: received['amount']) assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.4')-DEFAULT_FEE, r[0]['amount']) assert_equal(40000000-DEFAULT_FEE_ZATS, r[0]['amountZat']) - assert_true(r[0]['change'], "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change") + assert_equal(r[0]['change'], True, "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change") assert_equal(no_memo, r[0]['memo']) # The old note still exists (it's immutable), even though it is spent assert_equal(Decimal('1.0'), r[1]['amount']) assert_equal(100000000, r[1]['amountZat']) - assert_false(r[1]['change'], "Note valued at 1.0 should not be change") + assert_equal(r[1]['change'], False, "Note valued at 1.0 should not be change") assert_equal(my_memo, r[1]['memo']) # zaddr2 should not have change r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0) + assert_equal(len(r), 1, "zaddr2 Should have received 1 notes") r = sorted(r, key = lambda received: received['amount']) - assert_equal(1, len(r), "zaddr2 Should have received 1 notes") - assert_equal(txid, r[0]['txid']) - assert_equal(Decimal('0.6'), r[0]['amount']) - assert_equal(60000000, r[0]['amountZat']) - assert_false(r[0]['change'], "Note valued at 0.6 should not be change") - assert_equal(no_memo, r[0]['memo']) + assert_equal(r[0]['txid'], txid) + assert_equal(r[0]['amount'], Decimal('0.6')) + assert_equal(r[0]['amountZat'], 60000000) + assert_equal(r[0]['change'], False, "Note valued at 0.6 should not be change") + assert_equal(r[0]['memo'], no_memo) + assert 0 <= r[0]['outindex'] < 2 c = self.nodes[1].z_getnotescount(0) - assert_equal(3, c[release], "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)") + assert_equal(c['sapling'], 3, "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)") + + # As part of UA support, a transparent address is now accepted + r = self.nodes[1].z_listreceivedbyaddress(taddr, 0) + assert_equal(len(r), 1) + assert_equal(r[0]['pool'], 'transparent') + assert_equal(r[0]['txid'], txid_taddr) + assert_equal(r[0]['amount'], Decimal('4')) + assert_equal(r[0]['amountZat'], 400000000) + assert_equal(r[0]['confirmations'], 3) + assert 0 <= r[0]['outindex'] < 2 + + # Test unified address + node = self.nodes[1] + + # Create a unified address on one node, try z_listreceivedbyaddress on another node + account = self.nodes[0].z_getnewaccount()['account'] + r = self.nodes[0].z_getaddressforaccount(account) + unified_addr = r['unifiedaddress'] + # this address isn't in node1's wallet + assert_raises_message( + JSONRPCException, + "From address does not belong to this node", + node.z_listreceivedbyaddress, unified_addr, 0) + + # create a UA on node1 + r = node.z_getnewaccount() + account = r['account'] + r = node.z_getaddressforaccount(account) + unified_addr = r['unifiedaddress'] + receivers = node.z_listunifiedreceivers(unified_addr) + assert_equal(len(receivers), 3) + assert 'transparent' in receivers + assert 'sapling' in receivers + assert 'orchard' in receivers + assert_raises_message( + JSONRPCException, + "The provided address is a bare receiver from a Unified Address in this wallet.", + node.z_listreceivedbyaddress, receivers['transparent'], 0) + assert_raises_message( + JSONRPCException, + "The provided address is a bare receiver from a Unified Address in this wallet.", + node.z_listreceivedbyaddress, receivers['sapling'], 0) + + # Wallet contains no notes + r = node.z_listreceivedbyaddress(unified_addr, 0) + assert_equal(len(r), 0, "unified_addr should have received zero notes") + + # Create a note in this UA on node1 + opid = node.z_sendmany(zaddr1, [{'address': unified_addr, 'amount': 0.1}]) + txid_sapling = wait_and_assert_operationid_status(node, opid) + self.generate_and_sync(height+5) + + # Create a UTXO that unified_address's transparent component references, on node1 + outputs = {receivers['transparent']: 0.2} + txid_taddr = node.sendmany("", outputs) + + r = node.z_listreceivedbyaddress(unified_addr, 0) + assert_equal(len(r), 2, "unified_addr should have received 2 payments") + # The return list order isn't defined, so sort by pool name + r = sorted(r, key=lambda x: x['pool']) + assert_equal(r[0]['pool'], 'sapling') + assert_equal(r[0]['txid'], txid_sapling) + assert_equal(r[0]['amount'], Decimal('0.1')) + assert_equal(r[0]['amountZat'], 10000000) + assert_equal(r[0]['memo'], no_memo) + assert 0 <= r[0]['outindex'] < 2 + assert_equal(r[0]['confirmations'], 1) + assert_equal(r[0]['change'], False) + assert_equal(r[0]['blockheight'], height+5) + assert_equal(r[0]['blockindex'], 1) + assert 'blocktime' in r[0] + + assert_equal(r[1]['pool'], 'transparent') + assert_equal(r[1]['txid'], txid_taddr) + assert_equal(r[1]['amount'], Decimal('0.2')) + assert_equal(r[1]['amountZat'], 20000000) + assert 0 <= r[1]['outindex'] < 2 + assert_equal(r[1]['confirmations'], 0) + assert_equal(r[1]['change'], False) + assert 'memo' not in r[1] + assert_equal(r[1]['blockheight'], 0) # not yet mined + assert_equal(r[1]['blockindex'], -1) # not yet mined + assert 'blocktime' in r[1] + + def test_received_orchard(self, height): + self.generate_and_sync(height+1) + taddr = self.nodes[1].getnewaddress() + acct1 = self.nodes[1].z_getnewaccount()['account'] + acct2 = self.nodes[1].z_getnewaccount()['account'] + + addrResO = self.nodes[1].z_getaddressforaccount(acct1, ['orchard']) + assert_equal(addrResO['pools'], ['orchard']) + uao = addrResO['unifiedaddress'] + + addrResSO = self.nodes[1].z_getaddressforaccount(acct2, ['sapling', 'orchard']) + assert_equal(addrResSO['pools'], ['sapling', 'orchard']) + uaso = addrResSO['unifiedaddress'] + + self.nodes[0].sendtoaddress(taddr, 4.0) + self.generate_and_sync(height+2) + + acct_node0 = self.nodes[0].z_getnewaccount()['account'] + ua_node0 = self.nodes[0].z_getaddressforaccount(acct_node0, ['sapling', 'orchard'])['unifiedaddress'] + + opid = self.nodes[1].z_sendmany(taddr, [ + {'address': uao, 'amount': 1, 'memo': my_memo}, + {'address': uaso, 'amount': 2}, + ], 1, 0, 'AllowRevealedSenders') + txid0 = wait_and_assert_operationid_status(self.nodes[1], opid) + self.sync_all() + + # Decrypted transaction details should be correct, even though + # the transaction is still just in the mempool + pt = self.nodes[1].z_viewtransaction(txid0) + + assert_equal(pt['txid'], txid0) + assert_equal(len(pt['spends']), 0) + assert_equal(len(pt['outputs']), 2) + + # Outputs are not returned in a defined order but the amounts are deterministic + outputs = sorted(pt['outputs'], key=lambda x: x['valueZat']) + assert_equal(outputs[0]['type'], 'orchard') + assert_equal(outputs[0]['address'], uao) + assert_equal(outputs[0]['value'], Decimal('1')) + assert_equal(outputs[0]['valueZat'], 100000000) + assert_equal(outputs[0]['action'], 0) + assert_equal(outputs[0]['outgoing'], False) + assert_equal(outputs[0]['memo'], my_memo) + assert_equal(outputs[0]['memoStr'], my_memo_str) + + assert_equal(outputs[1]['type'], 'orchard') + assert_equal(outputs[1]['address'], uaso) + assert_equal(outputs[1]['value'], Decimal('2')) + assert_equal(outputs[1]['valueZat'], 200000000) + assert_equal(outputs[1]['action'], 1) + assert_equal(outputs[1]['outgoing'], False) + assert_equal(outputs[1]['memo'], no_memo) + assert 'memoStr' not in outputs[1] + + self.generate_and_sync(height+3) + + opid = self.nodes[1].z_sendmany(uao, [ + {'address': uaso, 'amount': Decimal('0.3')}, + {'address': ua_node0, 'amount': Decimal('0.2')} + ]) + txid1 = wait_and_assert_operationid_status(self.nodes[1], opid) + self.sync_all() + + pt = self.nodes[1].z_viewtransaction(txid1) + + assert_equal(pt['txid'], txid1) + assert_equal(len(pt['spends']), 1) # one spend we can see + assert_equal(len(pt['outputs']), 3) # one output + one change output we can see + + spends = pt['spends'] + assert_equal(spends[0]['type'], 'orchard') + assert_equal(spends[0]['action'], 0) + assert_equal(spends[0]['txidPrev'], txid0) + assert_equal(spends[0]['actionPrev'], 0) + assert_equal(spends[0]['address'], uao) + assert_equal(spends[0]['value'], Decimal('1.0')) + assert_equal(spends[0]['valueZat'], 100000000) + + outputs = sorted(pt['outputs'], key=lambda x: x['valueZat']) + assert_equal(outputs[0]['type'], 'orchard') + assert_equal(outputs[0]['address'], ua_node0) + assert_equal(outputs[0]['value'], Decimal('0.2')) + assert_equal(outputs[0]['valueZat'], 20000000) + assert_equal(outputs[0]['outgoing'], True) + assert_equal(outputs[0]['walletInternal'], False) + assert_equal(outputs[0]['memo'], no_memo) + + assert_equal(outputs[1]['type'], 'orchard') + assert_equal(outputs[1]['address'], uaso) + assert_equal(outputs[1]['value'], Decimal('0.3')) + assert_equal(outputs[1]['valueZat'], 30000000) + assert_equal(outputs[1]['outgoing'], False) + assert_equal(outputs[1]['walletInternal'], False) + assert_equal(outputs[1]['memo'], no_memo) + + # Verify that we observe the change output + print("###", uao, "###") + assert_equal(outputs[2]['type'], 'orchard') + assert_equal(outputs[2]['value'], Decimal('0.49999')) + assert_equal(outputs[2]['valueZat'], 49999000) + assert_equal(outputs[2]['outgoing'], False) + assert_equal(outputs[2]['walletInternal'], True) + assert_equal(outputs[2]['memo'], no_memo) + # The change address should have been erased + assert_true('address' not in outputs[2]) def run_test(self): - self.run_test_release('sprout', 200) - self.run_test_release('sapling', 214) + self.test_received_sprout(200) + self.test_received_sapling(214) + self.test_received_orchard(230) + if __name__ == '__main__': ListReceivedTest().main() diff --git a/qa/rpc-tests/wallet_orchard.py b/qa/rpc-tests/wallet_orchard.py new file mode 100755 index 00000000000..2a1ee85a697 --- /dev/null +++ b/qa/rpc-tests/wallet_orchard.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +# Copyright (c) 2022 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + NU5_BRANCH_ID, + assert_equal, + get_coinbase_address, + nuparams, + start_nodes, + wait_and_assert_operationid_status, +) + +from decimal import Decimal + +# Test wallet behaviour with the Orchard protocol +class WalletOrchardTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def setup_nodes(self): + return start_nodes(self.num_nodes, self.options.tmpdir, [[ + '-experimentalfeatures', + '-orchardwallet', + nuparams(NU5_BRANCH_ID, 210), + ]] * self.num_nodes) + + def run_test(self): + # Sanity-check the test harness + assert_equal(self.nodes[0].getblockcount(), 200) + + # Get a new orchard-only unified address + acct1 = self.nodes[1].z_getnewaccount()['account'] + addrRes1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard']) + assert_equal(acct1, addrRes1['account']) + assert_equal(addrRes1['pools'], ['orchard']) + ua1 = addrRes1['unifiedaddress'] + + # Verify that we have only an Orchard component + receiver_types = self.nodes[0].z_listunifiedreceivers(ua1) + assert_equal(set(['orchard']), set(receiver_types)) + + # Verify balance + assert_equal({'pools': {}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) + + # Send some sapling funds to node 2 for later spending after we split the network + acct2 = self.nodes[2].z_getnewaccount()['account'] + addrRes2 = self.nodes[2].z_getaddressforaccount(acct2, ['sapling', 'orchard']) + assert_equal(acct2, addrRes2['account']) + ua2 = addrRes2['unifiedaddress'] + saplingAddr2 = self.nodes[2].z_listunifiedreceivers(ua2)['sapling'] + + recipients = [{"address": saplingAddr2, "amount": Decimal('10')}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], myopid) + + # Mine the tx & activate NU5 + self.sync_all() + self.nodes[0].generate(10) + self.sync_all() + + # Check the value sent to saplingAddr2 was received in node 2's account + assert_equal( + {'pools': {'sapling': {'valueZat': Decimal('1000000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + # Node 0 shields some funds + # t-coinbase -> Orchard + recipients = [{"address": ua1, "amount": Decimal('10')}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], myopid) + + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('1000000000')}}, 'minimum_confirmations': 1}, + self.nodes[1].z_getbalanceforaccount(acct1)) + + # Split the network + self.split_network() + + # Send another tx to ua1 + recipients = [{"address": ua1, "amount": Decimal('10')}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], myopid) + + # Mine the tx & generate a majority chain on the 0/1 side of the split + self.sync_all() + self.nodes[0].generate(10) + self.sync_all() + + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('2000000000')}}, 'minimum_confirmations': 1}, + self.nodes[1].z_getbalanceforaccount(acct1)) + + # On the other side of the split, send some funds to node 3 + acct3 = self.nodes[3].z_getnewaccount()['account'] + addrRes3 = self.nodes[3].z_getaddressforaccount(acct3, ['sapling', 'orchard']) + assert_equal(acct3, addrRes3['account']) + ua3 = addrRes3['unifiedaddress'] + + recipients = [{"address": ua3, "amount": Decimal('1')}] + myopid = self.nodes[2].z_sendmany(ua2, recipients, 1, 0) + rollback_tx = wait_and_assert_operationid_status(self.nodes[2], myopid) + + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + + # The remaining change from ua2's Sapling note has been sent to the + # account's internal Orchard change address. + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 1}, + self.nodes[3].z_getbalanceforaccount(acct3)) + + # Check that the mempools are empty + for i in range(self.num_nodes): + assert_equal(set([]), set(self.nodes[i].getrawmempool())) + + # Reconnect the nodes; nodes 2 and 3 will re-org to node 0's chain. + print("Re-joining the network so that nodes 2 and 3 reorg") + self.join_network() + + # split 0/1's chain should have won, so their wallet balance should be consistent + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('2000000000')}}, 'minimum_confirmations': 1}, + self.nodes[1].z_getbalanceforaccount(acct1)) + + # split 2/3's chain should have been rolled back, so their txn should have been + # un-mined and returned to the mempool + assert_equal(set([rollback_tx]), set(self.nodes[2].getrawmempool())) + + # acct2's sole Orchard note is spent by a transaction in the mempool, so our + # confirmed balance is currently 0 + assert_equal( + {'pools': {}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + # acct2's incoming change (unconfirmed, still in the mempool) is 9 zec + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 0}, + self.nodes[2].z_getbalanceforaccount(acct2, 0)) + + # The transaction was un-mined, so acct3 should have no confirmed balance + assert_equal( + {'pools': {}, 'minimum_confirmations': 1}, + self.nodes[3].z_getbalanceforaccount(acct3)) + + # acct3's unconfirmed balance is 1 zec + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 0}, + self.nodes[3].z_getbalanceforaccount(acct3, 0)) + + # Manually resend the transaction in node 2's mempool + self.nodes[2].resendwallettransactions() + + # Sync the network + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # The un-mined transaction should now have been re-mined + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 1}, + self.nodes[3].z_getbalanceforaccount(acct3)) + +if __name__ == '__main__': + WalletOrchardTest().main() diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index fd2e3e069e7..5ccdd57b4e5 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -72,10 +72,8 @@ def run_test (self): # Node 0 shields to Node 2, a coinbase utxo of value 10.0 less default fee zsendamount = Decimal('10.0') - DEFAULT_FEE - recipients = [] - recipients.append({"address":zaddr2, "amount": zsendamount}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients) - txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) + result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr2, DEFAULT_FEE, 1) + txid_shielded = wait_and_assert_operationid_status(self.nodes[0], result['opid']) # Skip over the three blocks prior to activation; no transactions can be mined # in them due to the nearly-expiring restrictions. @@ -143,10 +141,8 @@ def run_test (self): # Node 0 shields to Node 3, a coinbase utxo of value 10.0 less default fee zsendamount = Decimal('10.0') - DEFAULT_FEE - recipients = [] - recipients.append({"address":zaddr3, "amount": zsendamount}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients) - txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) + result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr3, DEFAULT_FEE, 1) + txid_shielded = wait_and_assert_operationid_status(self.nodes[0], result['opid']) # Mine the first Blossom block self.sync_all() diff --git a/qa/rpc-tests/wallet_persistence.py b/qa/rpc-tests/wallet_persistence.py index 171201be2e7..7c8c348388a 100755 --- a/qa/rpc-tests/wallet_persistence.py +++ b/qa/rpc-tests/wallet_persistence.py @@ -36,7 +36,7 @@ def run_test(self): # Verify Sapling address is persisted in wallet sapling_addr = self.nodes[0].z_getnewaddress('sapling') - # Make sure the node has the addresss + # Make sure the node has the address addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address before restart") diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index ba9f17a91ee..19f88739d73 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -169,7 +169,7 @@ def run_test(self): ) raise AssertionError("Should have thrown an exception") except JSONRPCException as e: - assert_equal("Cannot send to both Sprout and Sapling addresses using z_sendmany", e.error['message']) + assert_equal("Sending funds into the Sprout pool is not supported by z_sendmany", e.error['message']) if __name__ == '__main__': WalletSaplingTest().main() diff --git a/qa/rpc-tests/wallet_sendmany_any_taddr.py b/qa/rpc-tests/wallet_sendmany_any_taddr.py index d88b09e2f31..0b44c38775d 100755 --- a/qa/rpc-tests/wallet_sendmany_any_taddr.py +++ b/qa/rpc-tests/wallet_sendmany_any_taddr.py @@ -6,29 +6,35 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + connect_nodes_bi, + start_nodes, + sync_blocks, wait_and_assert_operationid_status, ) +TX_EXPIRY_DELTA = 10 +TX_EXPIRING_SOON_THRESHOLD = 3 + # Test ANY_TADDR special string in z_sendmany class WalletSendManyAnyTaddr(BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(self.num_nodes, self.options.tmpdir, + [[ + "-txexpirydelta=%d" % TX_EXPIRY_DELTA, + ]] * self.num_nodes) + def run_test(self): # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) # Create the addresses we will be using. recipient = self.nodes[1].z_getnewaddress() + node2zaddr = self.nodes[2].z_getnewaddress() + node2taddr1 = self.nodes[2].getnewaddress() node3zaddr = self.nodes[3].z_getnewaddress() node3taddr1 = self.nodes[3].getnewaddress() node3taddr2 = self.nodes[3].getnewaddress() - # We should not be able to spend multiple coinbase UTXOs at once. - wait_and_assert_operationid_status( - self.nodes[3], - self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 100}]), - 'failed', - 'Could not find any non-coinbase UTXOs to spend. Coinbase UTXOs can only be sent to a single zaddr recipient from a single taddr.', - ) - # Prepare some non-coinbase UTXOs wait_and_assert_operationid_status( self.nodes[3], @@ -75,5 +81,48 @@ def run_test(self): assert_equal(self.nodes[3].z_getbalance(node3taddr1), 0) assert_equal(self.nodes[3].z_getbalance(node3taddr2), 0) + # Send from a change t-address. + wait_and_assert_operationid_status( + self.nodes[3], + self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}]), + ) + + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # The recipient has their funds! + assert_equal(self.nodes[1].z_getbalance(recipient), 120) + + # Check that ANY_TADDR note selection doesn't attempt a double-spend + myopid = self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}]) + wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds: have 14.99998, need 20.00001") + + # Create an expired transaction on node 3. + self.split_network() + expire_transparent = self.nodes[3].sendtoaddress(node2taddr1, 14) + assert(expire_transparent in self.nodes[3].getrawmempool()) + self.sync_all() + assert_equal('waiting', self.nodes[2].gettransaction(expire_transparent)['status']) + + self.nodes[0].generate(TX_EXPIRY_DELTA + TX_EXPIRING_SOON_THRESHOLD) + self.sync_all() + connect_nodes_bi(self.nodes, 1, 2) + sync_blocks(self.nodes[1:3]) + assert_equal('expired', self.nodes[2].gettransaction(expire_transparent)['status']) + + # Ensure that node 2 has no transparent funds. + self.nodes[2].generate(100) # To ensure node 2's pending coinbase is spendable + self.sync_all() + wait_and_assert_operationid_status( + self.nodes[2], + self.nodes[2].z_shieldcoinbase("*", node2zaddr, 0)['opid'], + ) + self.sync_all() + assert_equal(0, self.nodes[2].getbalance()) + + # Check that ANY_TADDR doesn't select an expired output. + wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 13}]), "failed", "Insufficient funds: have 0.00, need 13.00001") + if __name__ == '__main__': WalletSendManyAnyTaddr().main() diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py index ccb1e68a8e9..a7731751ac1 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase.py +++ b/qa/rpc-tests/wallet_shieldcoinbase.py @@ -7,21 +7,24 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, initialize_chain_clean, \ start_node, connect_nodes_bi, sync_blocks, sync_mempools, \ - wait_and_assert_operationid_status, get_coinbase_address, DEFAULT_FEE + wait_and_assert_operationid_status, get_coinbase_address, DEFAULT_FEE, \ + NU5_BRANCH_ID, nuparams from decimal import Decimal class WalletShieldCoinbaseTest (BitcoinTestFramework): - def __init__(self, addr_type): - super(WalletShieldCoinbaseTest, self).__init__() - self.addr_type = addr_type - def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self, split=False): - args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe'] + args = [ + '-regtestprotectcoinbase', + '-debug=zrpcunsafe', + '-experimentalfeatures', + '-orchardwallet', + nuparams(NU5_BRANCH_ID, self.nu5_activation), + ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) self.nodes.append(start_node(1, self.options.tmpdir, args)) @@ -52,11 +55,13 @@ def run_test (self): assert_equal(self.nodes[1].getbalance(), 10) assert_equal(self.nodes[2].getbalance(), 30) + # create one zaddr that is the target of all shielding + myzaddr = self.test_init_zaddr(self.nodes[0]) + do_not_shield_taddr = get_coinbase_address(self.nodes[0], 1) # Prepare to send taddr->zaddr mytaddr = get_coinbase_address(self.nodes[0], 4) - myzaddr = self.nodes[0].z_getnewaddress(self.addr_type) # Shielding will fail when trying to spend from watch-only address self.nodes[2].importaddress(mytaddr) @@ -111,7 +116,7 @@ def run_test (self): # Confirm balances and that do_not_shield_taddr containing funds of 10 was left alone assert_equal(self.nodes[0].getbalance(), 10) assert_equal(self.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0')) - assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('40.0') - DEFAULT_FEE) + self.test_check_balance_zaddr(self.nodes[0], Decimal('40.0') - DEFAULT_FEE) assert_equal(self.nodes[1].getbalance(), 20) assert_equal(self.nodes[2].getbalance(), 30) @@ -123,7 +128,7 @@ def run_test (self): self.sync_all() assert_equal(self.nodes[0].getbalance(), 10) - assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('70.0') - DEFAULT_FEE) + self.test_check_balance_zaddr(self.nodes[0], Decimal('70.0') - DEFAULT_FEE) assert_equal(self.nodes[1].getbalance(), 30) assert_equal(self.nodes[2].getbalance(), 0) @@ -151,7 +156,7 @@ def verify_locking(first, second, limit): assert_equal(result["remainingUTXOs"], Decimal('0')) opid2 = result['opid'] - # wait for both aysnc operations to complete + # wait for both async operations to complete wait_and_assert_operationid_status(self.nodes[0], opid1) wait_and_assert_operationid_status(self.nodes[0], opid2) @@ -185,3 +190,6 @@ def verify_locking(first, second, limit): sync_mempools(self.nodes[:2]) self.nodes[1].generate(1) self.sync_all() + +# Note, no "if __name__ == '__main__" and call the test here; it's called from +# pool-specific derived classes in wallet_shieldcoinbase_*.py \ No newline at end of file diff --git a/qa/rpc-tests/wallet_shieldcoinbase_sapling.py b/qa/rpc-tests/wallet_shieldcoinbase_sapling.py index 2e533434952..5e3cc2a3911 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase_sapling.py +++ b/qa/rpc-tests/wallet_shieldcoinbase_sapling.py @@ -1,10 +1,22 @@ #!/usr/bin/env python3 -from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from test_framework.util import assert_equal class WalletShieldCoinbaseSapling(WalletShieldCoinbaseTest): def __init__(self): - super(WalletShieldCoinbaseSapling, self).__init__('sapling') + super(WalletShieldCoinbaseSapling, self).__init__() + self.nu5_activation = 99999 + + def test_init_zaddr(self, node): + self.addr = node.z_getnewaddress('sapling') + return self.addr + + def test_check_balance_zaddr(self, node, expected): + balance = node.z_getbalance(self.addr) + assert_equal(balance, expected) + if __name__ == '__main__': + print("Test shielding to a sapling address") WalletShieldCoinbaseSapling().main() diff --git a/qa/rpc-tests/wallet_shieldcoinbase_sprout.py b/qa/rpc-tests/wallet_shieldcoinbase_sprout.py index d32201b404a..2e7fc7f7c99 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase_sprout.py +++ b/qa/rpc-tests/wallet_shieldcoinbase_sprout.py @@ -1,10 +1,22 @@ #!/usr/bin/env python3 -from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from test_framework.util import assert_equal class WalletShieldCoinbaseSprout(WalletShieldCoinbaseTest): def __init__(self): - super(WalletShieldCoinbaseSprout, self).__init__('sprout') + super(WalletShieldCoinbaseSprout, self).__init__() + self.nu5_activation = 99999 + + def test_init_zaddr(self, node): + self.addr = node.z_getnewaddress('sprout') + return self.addr + + def test_check_balance_zaddr(self, node, expected): + balance = node.z_getbalance(self.addr) + assert_equal(balance, expected) + if __name__ == '__main__': + print("Test shielding to a sapling address") WalletShieldCoinbaseSprout().main() diff --git a/qa/rpc-tests/wallet_shieldcoinbase_ua_nu5.py b/qa/rpc-tests/wallet_shieldcoinbase_ua_nu5.py new file mode 100755 index 00000000000..30a7f22fba3 --- /dev/null +++ b/qa/rpc-tests/wallet_shieldcoinbase_ua_nu5.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from test_framework.util import assert_equal +from test_framework.mininode import COIN + +class WalletShieldCoinbaseUANU5(WalletShieldCoinbaseTest): + def __init__(self): + super(WalletShieldCoinbaseUANU5, self).__init__() + self.account = None + # activate after initial setup, before the first z_shieldcoinbase RPC + self.nu5_activation = 109 + + def test_init_zaddr(self, node): + # this function may be called no more than once + assert(self.account is None) + self.account = node.z_getnewaccount()['account'] + self.addr = node.z_getaddressforaccount(self.account)['unifiedaddress'] + return self.addr + + def test_check_balance_zaddr(self, node, expected): + balances = node.z_getbalanceforaccount(self.account) + assert('transparent' not in balances['pools']) + assert('sprout' not in balances['pools']) + # assert('sapling' not in balances['pools']) + sapling_balance = balances['pools']['sapling']['valueZat'] + assert_equal(sapling_balance, expected * COIN) + # assert_equal(balances['pools']['orchard']['valueZat'], expected * COIN) + + # While we're at it, check that z_listunspent only shows outputs with + # the Unified Address (not the Orchard receiver), and of the expected + # type. + unspent = node.z_listunspent(1, 999999, False, [self.addr]) + assert_equal( + [{'type': 'sapling', 'address': self.addr} for _ in unspent], + [{'type': x['type'], 'address': x['address']} for x in unspent], + ) + + total_balance = node.z_getbalance(self.addr) * COIN + assert_equal(total_balance, sapling_balance) + +if __name__ == '__main__': + print("Test shielding to a unified address with NU5 activated") + WalletShieldCoinbaseUANU5().main() diff --git a/qa/rpc-tests/wallet_shieldcoinbase_ua_sapling.py b/qa/rpc-tests/wallet_shieldcoinbase_ua_sapling.py new file mode 100755 index 00000000000..f07ef656ee3 --- /dev/null +++ b/qa/rpc-tests/wallet_shieldcoinbase_ua_sapling.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +from wallet_shieldcoinbase import WalletShieldCoinbaseTest +from test_framework.util import assert_equal +from test_framework.mininode import COIN + +class WalletShieldCoinbaseUASapling(WalletShieldCoinbaseTest): + def __init__(self): + super(WalletShieldCoinbaseUASapling, self).__init__() + self.account = None + self.nu5_activation = 99999 + + def test_init_zaddr(self, node): + # this function may be called no more than once + assert(self.account is None) + self.account = node.z_getnewaccount()['account'] + self.addr = node.z_getaddressforaccount(self.account)['unifiedaddress'] + return self.addr + + def test_check_balance_zaddr(self, node, expected): + balances = node.z_getbalanceforaccount(self.account) + assert('transparent' not in balances['pools']) + assert('sprout' not in balances['pools']) + sapling_balance = balances['pools']['sapling']['valueZat'] + assert_equal(sapling_balance, expected * COIN) + assert('orchard' not in balances['pools']) + + # While we're at it, check that z_listunspent only shows outputs with + # the Unified Address (not the Sapling receiver), and of the expected + # type. + unspent = node.z_listunspent(1, 999999, False, [self.addr]) + assert_equal( + [{'type': 'sapling', 'address': self.addr} for _ in unspent], + [{'type': x['type'], 'address': x['address']} for x in unspent], + ) + + total_balance = node.z_getbalance(self.addr) * COIN + assert_equal(total_balance, sapling_balance) + +if __name__ == '__main__': + print("Test shielding to a unified address with sapling activated (but not NU5)") + WalletShieldCoinbaseUASapling().main() diff --git a/qa/rpc-tests/wallet_shieldingcoinbase.py b/qa/rpc-tests/wallet_shieldingcoinbase.py index c6be8fdce53..f8a3b9ed74c 100755 --- a/qa/rpc-tests/wallet_shieldingcoinbase.py +++ b/qa/rpc-tests/wallet_shieldingcoinbase.py @@ -61,10 +61,10 @@ def run_test (self): assert_equal(self.nodes[2].getbalance(), 0) assert_equal(self.nodes[3].getbalance(), 0) - check_value_pool(self.nodes[0], 'sprout', 0) - check_value_pool(self.nodes[1], 'sprout', 0) - check_value_pool(self.nodes[2], 'sprout', 0) - check_value_pool(self.nodes[3], 'sprout', 0) + check_value_pool(self.nodes[0], 'sapling', 0) + check_value_pool(self.nodes[1], 'sapling', 0) + check_value_pool(self.nodes[2], 'sapling', 0) + check_value_pool(self.nodes[3], 'sapling', 0) # Send will fail because we are enforcing the consensus rule that # coinbase utxos can only be sent to a zaddr. @@ -77,24 +77,31 @@ def run_test (self): # Prepare to send taddr->zaddr mytaddr = get_coinbase_address(self.nodes[0]) - myzaddr = self.nodes[0].z_getnewaddress('sprout') + myzaddr = self.nodes[0].z_getnewaddress('sapling') # Node 3 will test that watch only address utxos are not selected self.nodes[3].importaddress(mytaddr) recipients= [{"address":myzaddr, "amount": Decimal('1')}] - myopid = self.nodes[3].z_sendmany(mytaddr, recipients) - - wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient transparent funds, no UTXOs found for taddr from address.", 10) + try: + myopid = self.nodes[3].z_sendmany(mytaddr, recipients) + except JSONRPCException as e: + errorString = e.error['message'] + assert_equal("Invalid from address, no payment source found for address.", errorString); - # This send will fail because our wallet does not allow any change when shielding a coinbase utxo, - # as it's currently not possible to specify a change address in z_sendmany. + # This send will fail because our consensus does not allow transparent change when + # shielding a coinbase utxo. + # TODO: After upgrading to unified address support, change will be sent to the most + # recent shielded spend authority corresponding to the account of the source address + # and this send will succeed, causing this test to fail. recipients = [] recipients.append({"address":myzaddr, "amount":Decimal('1.23456789')}) myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - error_result = wait_and_assert_operationid_status_result(self.nodes[0], myopid, "failed", ("Change 8.76542211 not allowed. " - "When shielding coinbase funds, the wallet does not allow any change " - "as there is currently no way to specify a change address in z_sendmany."), 10) + error_result = wait_and_assert_operationid_status_result( + self.nodes[0], + myopid, "failed", + "When shielding coinbase funds, the wallet does not allow any change. The proposed transaction would result in 8.76542211 in change.", + 10) # Test that the returned status object contains a params field with the operation's input parameters assert_equal(error_result["method"], "z_sendmany") @@ -122,6 +129,7 @@ def run_test (self): assert(len(results) == 0) results = self.nodes[0].z_listunspent(0) # set minconf to zero assert(len(results) == 1) + assert_equal(results[0]["type"], "sapling") assert_equal(results[0]["address"], myzaddr) assert_equal(results[0]["amount"], shieldvalue) assert_equal(results[0]["confirmations"], 0) @@ -133,6 +141,7 @@ def run_test (self): # Verify that z_listunspent returns one note which has been confirmed results = self.nodes[0].z_listunspent() assert(len(results) == 1) + assert_equal(results[0]["type"], "sapling") assert_equal(results[0]["address"], myzaddr) assert_equal(results[0]["amount"], shieldvalue) assert_equal(results[0]["confirmations"], 1) @@ -141,6 +150,7 @@ def run_test (self): # Verify that z_listunspent returns note for watchonly address on node 3. results = self.nodes[3].z_listunspent(1, 999, True) assert(len(results) == 1) + assert_equal(results[0]["type"], "sapling") assert_equal(results[0]["address"], myzaddr) assert_equal(results[0]["amount"], shieldvalue) assert_equal(results[0]["confirmations"], 1) @@ -151,7 +161,7 @@ def run_test (self): results = self.nodes[1].z_listunspent(1, 999, False, [myzaddr]) except JSONRPCException as e: errorString = e.error['message'] - assert_equal("Invalid parameter, spending key for address does not belong to wallet" in errorString, True) + assert_equal("Invalid parameter, spending key for an address does not belong to the wallet.", errorString) # Verify that debug=zrpcunsafe logs params, and that full txid is associated with opid initialized_line = check_node_log(self, 0, myopid + ": z_sendmany initialized", False) @@ -165,8 +175,8 @@ def run_test (self): assert_equal(Decimal(resp["total"]), Decimal('40.0') - DEFAULT_FEE) # The Sprout value pool should reflect the send - sproutvalue = shieldvalue - check_value_pool(self.nodes[0], 'sprout', sproutvalue) + saplingvalue = shieldvalue + check_value_pool(self.nodes[0], 'sapling', saplingvalue) # A custom fee of 0 is okay. Here the node will send the note value back to itself. recipients = [] @@ -181,8 +191,8 @@ def run_test (self): assert_equal(Decimal(resp["private"]), Decimal('20.0') - DEFAULT_FEE) assert_equal(Decimal(resp["total"]), Decimal('40.0') - DEFAULT_FEE) - # The Sprout value pool should be unchanged - check_value_pool(self.nodes[0], 'sprout', sproutvalue) + # The Sapling value pool should be unchanged + check_value_pool(self.nodes[0], 'sapling', saplingvalue) # convert note to transparent funds unshieldvalue = Decimal('10.0') @@ -201,12 +211,12 @@ def run_test (self): self.sync_all() # check balances - sproutvalue -= unshieldvalue + DEFAULT_FEE + saplingvalue -= unshieldvalue + DEFAULT_FEE resp = self.nodes[0].z_gettotalbalance() assert_equal(Decimal(resp["transparent"]), Decimal('30.0')) assert_equal(Decimal(resp["private"]), Decimal('10.0') - 2*DEFAULT_FEE) assert_equal(Decimal(resp["total"]), Decimal('40.0') - 2*DEFAULT_FEE) - check_value_pool(self.nodes[0], 'sprout', sproutvalue) + check_value_pool(self.nodes[0], 'sapling', saplingvalue) # z_sendmany will return an error if there is transparent change output considered dust. # UTXO selection in z_sendmany sorts in ascending order, so smallest utxos are consumed first. @@ -215,7 +225,7 @@ def run_test (self): amount = Decimal('10.0') - DEFAULT_FEE - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold recipients.append({"address":self.nodes[0].getnewaddress(), "amount":amount }) myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)") + wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)") # Send will fail because send amount is too big, even when including coinbase utxos errorString = "" @@ -229,9 +239,9 @@ def run_test (self): recipients = [] recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')}) myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 10000.00001") + wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 10.00, need 10000.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR or if any transparent recipients are included.") myopid = self.nodes[0].z_sendmany(myzaddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient shielded funds, have 9.99998, need 10000.00001") + wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 9.99998, need 10000.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR or if any transparent recipients are included.") # Send will fail because of insufficient funds unless sender uses coinbase utxos try: @@ -282,9 +292,9 @@ def run_test (self): # check balance node2balance = amount_per_recipient * num_t_recipients - sproutvalue -= node2balance + DEFAULT_FEE + saplingvalue -= node2balance + DEFAULT_FEE assert_equal(self.nodes[2].getbalance(), node2balance) - check_value_pool(self.nodes[0], 'sprout', sproutvalue) + check_value_pool(self.nodes[0], 'sapling', saplingvalue) # Send will fail because fee is negative try: @@ -330,7 +340,7 @@ def run_test (self): custom_fee = Decimal('0.00012345') zbalance = self.nodes[0].z_getbalance(myzaddr) for i in range(0,num_recipients): - newzaddr = self.nodes[2].z_getnewaddress('sprout') + newzaddr = self.nodes[2].z_getnewaddress('sapling') recipients.append({"address":newzaddr, "amount":amount_per_recipient}) myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, custom_fee) wait_and_assert_operationid_status(self.nodes[0], myopid) @@ -348,8 +358,8 @@ def run_test (self): resp = self.nodes[0].z_getbalance(myzaddr) assert_equal(Decimal(resp), zbalance - custom_fee - send_amount) - sproutvalue -= custom_fee - check_value_pool(self.nodes[0], 'sprout', sproutvalue) + saplingvalue -= custom_fee + check_value_pool(self.nodes[0], 'sapling', saplingvalue) notes = self.nodes[0].z_listunspent(1, 99999, False, [myzaddr]) sum_of_notes = sum([note["amount"] for note in notes]) diff --git a/qa/rpc-tests/wallet_z_sendmany.py b/qa/rpc-tests/wallet_z_sendmany.py index 6afc1fe2a16..dd1559305b8 100755 --- a/qa/rpc-tests/wallet_z_sendmany.py +++ b/qa/rpc-tests/wallet_z_sendmany.py @@ -4,21 +4,52 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php . from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi, \ - DEFAULT_FEE, start_nodes, wait_and_assert_operationid_status +from test_framework.util import ( + assert_equal, + assert_greater_than, + assert_raises_message, + connect_nodes_bi, + DEFAULT_FEE, + start_nodes, + wait_and_assert_operationid_status, +) from test_framework.authproxy import JSONRPCException +from test_framework.mininode import COIN from decimal import Decimal # Test wallet address behaviour across network upgrades class WalletZSendmanyTest(BitcoinTestFramework): def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(3, self.options.tmpdir, [[ + '-experimentalfeatures', + '-orchardwallet', + ]] * self.num_nodes) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) self.is_network_split=False self.sync_all() + # Check we only have balances in the expected pools. + # Remember that empty pools are omitted from the output. + def _check_balance_for_rpc(self, rpcmethod, node, account, expected, minconf): + rpc = getattr(self.nodes[node], rpcmethod) + actual = rpc(account, minconf) + assert_equal(set(expected), set(actual['pools'])) + total_balance = 0 + for pool in expected: + assert_equal(expected[pool] * COIN, actual['pools'][pool]['valueZat']) + total_balance += expected[pool] + assert_equal(actual['minimum_confirmations'], minconf) + return total_balance + + def check_balance(self, node, account, address, expected, minconf=1): + acct_balance = self._check_balance_for_rpc('z_getbalanceforaccount', node, account, expected, minconf) + z_getbalance = self.nodes[node].z_getbalance(address, minconf) + assert_equal(acct_balance, z_getbalance) + fvk = self.nodes[node].z_exportviewingkey(address) + self._check_balance_for_rpc('z_getbalanceforviewingkey', node, fvk, expected, minconf) + def run_test(self): # z_sendmany is expected to fail if tx size breaks limit myzaddr = self.nodes[0].z_getnewaddress() @@ -65,8 +96,8 @@ def run_test(self): # send node 2 taddr to zaddr recipients = [] recipients.append({"address":myzaddr, "amount":7}) - - mytxid = wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(mytaddr, recipients)) + opid = self.nodes[2].z_sendmany(mytaddr, recipients) + mytxid = wait_and_assert_operationid_status(self.nodes[2], opid) self.sync_all() @@ -87,13 +118,14 @@ def run_test(self): assert_equal(self.nodes[2].getbalance("*"), node2utxobalance) # check zaddr balance with z_getbalance - assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue) + zbalance = zsendmanynotevalue + assert_equal(self.nodes[2].z_getbalance(myzaddr), zbalance) # check via z_gettotalbalance resp = self.nodes[2].z_gettotalbalance() assert_equal(Decimal(resp["transparent"]), node2utxobalance) - assert_equal(Decimal(resp["private"]), zsendmanynotevalue) - assert_equal(Decimal(resp["total"]), node2utxobalance + zsendmanynotevalue) + assert_equal(Decimal(resp["private"]), zbalance) + assert_equal(Decimal(resp["total"]), node2utxobalance + zbalance) # check confirmed shielded balance with getwalletinfo wallet_info = self.nodes[2].getwalletinfo() @@ -118,7 +150,9 @@ def run_test(self): recipients.append({"address":self.nodes[0].getnewaddress(), "amount":1}) recipients.append({"address":self.nodes[2].getnewaddress(), "amount":1.0}) - wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(myzaddr, recipients)) + opid = self.nodes[2].z_sendmany(myzaddr, recipients) + wait_and_assert_operationid_status(self.nodes[2], opid) + zbalance -= Decimal('2.0') + zsendmanyfee self.sync_all() self.nodes[2].generate(1) @@ -131,5 +165,225 @@ def run_test(self): assert_equal(Decimal(self.nodes[2].getbalance()), node2balance) assert_equal(Decimal(self.nodes[2].getbalance("*")), node2balance) + # Get a new unified account on node 2 & generate a UA + n0account0 = self.nodes[0].z_getnewaccount()['account'] + n0ua0 = self.nodes[0].z_getaddressforaccount(n0account0)['unifiedaddress'] + + # Change went to a fresh address, so use `ANY_TADDR` which + # should hold the rest of our transparent funds. + source = 'ANY_TADDR' + recipients = [] + recipients.append({"address":n0ua0, "amount":10}) + + # If we attempt to spend with the default privacy policy, z_sendmany + # fails because it needs to spend transparent coins in a transaction + # involving a Unified Address. + revealed_senders_msg = 'This transaction requires selecting transparent coins, which is not enabled by default because it will publicly reveal transaction senders and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedSenders` or weaker if you wish to allow this transaction to proceed anyway.' + opid = self.nodes[2].z_sendmany(source, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg) + + # We can't create a transaction with an unknown privacy policy. + assert_raises_message( + JSONRPCException, + 'Unknown privacy policy name \'ZcashIsAwesome\'', + self.nodes[2].z_sendmany, + source, recipients, 1, 0, 'ZcashIsAwesome') + + # If we set any policy that does not include AllowRevealedSenders, + # z_sendmany also fails. + for policy in [ + 'FullPrivacy', + 'AllowRevealedAmounts', + 'AllowRevealedRecipients', + ]: + opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, policy) + wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg) + + # By setting the correct policy, we can create the transaction. + opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[2], opid) + + self.nodes[2].generate(1) + self.sync_all() + + node2balance -= Decimal('10.0') + node0balance += Decimal('10.0') + assert_equal(Decimal(self.nodes[2].getbalance()), node2balance) + assert_equal(Decimal(self.nodes[0].getbalance()), node0balance) + self.check_balance(0, 0, n0ua0, {'sapling': 10}) + + # Send some funds to a specific legacy taddr that we can spend from + recipients = [] + recipients.append({"address":mytaddr, "amount":5}) + + # If we attempt to spend with the default privacy policy, z_sendmany + # returns an error because it needs to create a transparent recipient in + # a transaction involving a Unified Address. + assert_raises_message( + JSONRPCException, + 'AllowRevealedRecipients', + self.nodes[0].z_sendmany, + n0ua0, recipients, 1, 0) + + # If we set any policy that does not include AllowRevealedRecipients, + # z_sendmany also returns an error. + for policy in [ + 'FullPrivacy', + 'AllowRevealedAmounts', + 'AllowRevealedSenders', + 'AllowLinkingAccountAddresses', + ]: + assert_raises_message( + JSONRPCException, + 'AllowRevealedRecipients', + self.nodes[0].z_sendmany, + n0ua0, recipients, 1, 0, policy) + + # By setting the correct policy, we can create the transaction. + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, 'AllowRevealedRecipients') + wait_and_assert_operationid_status(self.nodes[0], opid) + + self.nodes[0].generate(1) + self.sync_all() + + node2balance += Decimal('5.0') + self.check_balance(0, 0, n0ua0, {'sapling': 5}) + assert_equal(Decimal(self.nodes[2].getbalance()), node2balance) + + # Send some funds to a legacy sapling address that we can spend from + recipients = [] + recipients.append({"address":myzaddr, "amount":3}) + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + + self.nodes[0].generate(1) + self.sync_all() + + zbalance += Decimal('3.0') + self.check_balance(0, 0, n0ua0, {'sapling': 2}) + assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance) + + # Send funds back from the legacy taddr to the UA. This requires + # AllowRevealedSenders, but we can also use any weaker policy that + # includes it. + recipients = [] + recipients.append({"address":n0ua0, "amount":4}) + opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0, 'AllowFullyTransparent') + wait_and_assert_operationid_status(self.nodes[2], opid) + + self.nodes[2].generate(1) + self.sync_all() + + node2balance -= Decimal('4.0') + self.check_balance(0, 0, n0ua0, {'sapling': 6}) + assert_equal(Decimal(self.nodes[2].getbalance()), node2balance) + + # Send funds back from the legacy zaddr to the UA + recipients = [] + recipients.append({"address":n0ua0, "amount":2}) + opid = self.nodes[2].z_sendmany(myzaddr, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[2], opid) + + self.nodes[2].generate(1) + self.sync_all() + + zbalance -= Decimal('2.0') + self.check_balance(0, 0, n0ua0, {'sapling': 8}) + assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance) + + # + # Test that z_sendmany avoids UA linkability unless we allow it. + # + + # Generate a new account with two new addresses. + n1account = self.nodes[1].z_getnewaccount()['account'] + n1ua0 = self.nodes[1].z_getaddressforaccount(n1account)['unifiedaddress'] + n1ua1 = self.nodes[1].z_getaddressforaccount(n1account)['unifiedaddress'] + + # Send funds to the transparent receivers of both addresses. + for ua in [n1ua0, n1ua1]: + taddr = self.nodes[1].z_listunifiedreceivers(ua)['transparent'] + self.nodes[0].sendtoaddress(taddr, 2) + + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + + # The account should see all funds. + assert_equal( + self.nodes[1].z_getbalanceforaccount(n1account)['pools'], + {'transparent': {'valueZat': 4 * COIN}}, + ) + + # The addresses should see only the transparent funds sent to them. + assert_equal(self.nodes[1].z_getbalance(n1ua0), 2) + assert_equal(self.nodes[1].z_getbalance(n1ua1), 2) + + # If we try to send 3 ZEC from n1ua0, it will fail with too-few funds. + recipients = [{"address":n0ua0, "amount":3}] + linked_addrs_msg = 'Insufficient funds: have 2.00, need 3.00 (This transaction may require selecting transparent coins that were sent to multiple Unified Addresses, which is not enabled by default because it would create a public link between the transparent receivers of these addresses. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowLinkingAccountAddresses` or weaker if you wish to allow this transaction to proceed anyway.)' + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', linked_addrs_msg) + + # If we try it again with any policy that is too strong, it also fails. + for policy in [ + 'FullPrivacy', + 'AllowRevealedAmounts', + 'AllowRevealedRecipients', + 'AllowRevealedSenders', + 'AllowFullyTransparent', + ]: + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy) + wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', linked_addrs_msg) + + # Once we provide a sufficiently-weak policy, the transaction succeeds. + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowLinkingAccountAddresses') + wait_and_assert_operationid_status(self.nodes[1], opid) + + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + + # The account should see the remaining funds, and they should have been + # sent to the Sapling change address (because NU5 is not active). + assert_equal( + self.nodes[1].z_getbalanceforaccount(n1account)['pools'], + {'sapling': {'valueZat': 1 * COIN}}, + ) + + # The addresses should both show the same balance, as they both show the + # Sapling balance. + assert_equal(self.nodes[1].z_getbalance(n1ua0), 1) + assert_equal(self.nodes[1].z_getbalance(n1ua1), 1) + + # + # Test NoPrivacy policy + # + + # Send some legacy transparent funds to n1ua0, creating Sapling outputs. + recipients = [{"address":n1ua0, "amount":10}] + # This requires the AllowRevealedSenders policy... + opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg) + # ... which we can always override with the NoPrivacy policy. + opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0, 'NoPrivacy') + wait_and_assert_operationid_status(self.nodes[2], opid) + + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + + # Send some funds from node 1's account to a transparent address. + recipients = [{"address":mytaddr, "amount":5}] + # This requires the AllowRevealedRecipients policy... + assert_raises_message( + JSONRPCException, + 'AllowRevealedRecipients', + self.nodes[1].z_sendmany, + n1ua0, recipients, 1, 0) + # ... which we can always override with the NoPrivacy policy. + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'NoPrivacy') + wait_and_assert_operationid_status(self.nodes[1], opid) + if __name__ == '__main__': WalletZSendmanyTest().main() diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index 463fe63b05e..ee2f8846052 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -96,10 +96,10 @@ def do_one_round(self): self.sync_all() # As above, this mirrors the original bash test. - def start_three(self): - self.nodes[0] = start_node(0, self.options.tmpdir) - self.nodes[1] = start_node(1, self.options.tmpdir) - self.nodes[2] = start_node(2, self.options.tmpdir) + def start_three(self, extra_args=None): + self.nodes[0] = start_node(0, self.options.tmpdir, extra_args) + self.nodes[1] = start_node(1, self.options.tmpdir, extra_args) + self.nodes[2] = start_node(2, self.options.tmpdir, extra_args) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) @@ -191,6 +191,29 @@ def run_test(self): self.start_three() sync_blocks(self.nodes) + # We made extra transactions that involved addresses generated after the + # backups were taken, and external addresses do not use the keypool, so + # the balances shouldn't line up. + balance0backup = self.nodes[0].getbalance() + balance1backup = self.nodes[1].getbalance() + balance2backup = self.nodes[2].getbalance() + assert(balance0backup != balance0) + assert(balance1backup != balance1) + assert(balance2backup != balance2) + + # However, because addresses are derived deterministically, we can + # recover the balances by generating the extra addresses and then + # rescanning. + for i in range(5): + self.nodes[0].getnewaddress() + self.nodes[1].getnewaddress() + self.nodes[2].getnewaddress() + + logging.info("Re-starting nodes with -rescan") + self.stop_three() + self.start_three(['-rescan']) + sync_blocks(self.nodes) + assert_equal(self.nodes[0].getbalance(), balance0) assert_equal(self.nodes[1].getbalance(), balance1) assert_equal(self.nodes[2].getbalance(), balance2) @@ -215,9 +238,9 @@ def run_test(self): sync_blocks(self.nodes) - assert_equal(self.nodes[0].getbalance(), balance0) - assert_equal(self.nodes[1].getbalance(), balance1) - assert_equal(self.nodes[2].getbalance(), balance2) + assert_equal(self.nodes[0].getbalance(), balance0backup) + assert_equal(self.nodes[1].getbalance(), balance1backup) + assert_equal(self.nodes[2].getbalance(), balance2backup) if __name__ == '__main__': diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index 9985eb89b44..1f02234dbf8 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -75,7 +75,7 @@ def run_test (self): print(e) aException = True - assert_equal(aException, True) # there must be a expection because the unconfirmed wallettx0 must be gone by now + assert_equal(aException, True) # there must be an exception because the unconfirmed wallet tx0 must be gone by now tx0 = self.nodes[0].gettransaction(txid0) assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed diff --git a/qa/zcash/checksec.sh b/qa/zcash/checksec.sh index ba382062724..be594ea6193 100755 --- a/qa/zcash/checksec.sh +++ b/qa/zcash/checksec.sh @@ -39,7 +39,7 @@ # Name : checksec.sh # Version : 1.7.0 # Author : Brian Davis -# Date : Feburary 2014 +# Date : February 2014 # Download: https://github.com/slimm609/checksec.sh # # --- Modified Version --- @@ -298,9 +298,9 @@ echo_message() { # check selinux status getsestatus() { local status - ${debug} && echo -e "\n***fuction getsestatus" + ${debug} && echo -e "\n***function getsestatus" if (command_exists getenforce); then - ${debug} && echo "***fuction getsestatus->getenforce" + ${debug} && echo "***function getsestatus->getenforce" sestatus=$(getenforce) if [[ "${sestatus}" == "Disabled" ]]; then status=0 @@ -310,7 +310,7 @@ getsestatus() { status=2 fi elif (command_exists sestatus); then - ${debug} && echo "***fuction getsestatus->sestatus" + ${debug} && echo "***function getsestatus->sestatus" sestatus=$(sestatus | grep "SELinux status" | awk '{ print $3}') if [[ "${sestatus}" == "disabled" ]]; then status=0 @@ -328,7 +328,7 @@ return ${status} # check if directory exists dir_exists () { - ${debug} && echo "fuction dir_exists" + ${debug} && echo "function dir_exists" if [[ -d "${1}" ]] ; then return 0 else @@ -842,7 +842,7 @@ kernelcheck() { fi echo_message " Kernel heap randomization: " "" "" "" - # NOTE: y means it turns off kernel heap randomization for backwards compatability (libc5) + # NOTE: y means it turns off kernel heap randomization for backwards compatibility (libc5) if ${kconfig} | grep -qi 'CONFIG_COMPAT_BRK=y'; then echo_message "\033[31mDisabled\033[m\n" "Disabled," " kernel_heap_randomization='no'" ', "kernel_heap_randomization":"no"' else @@ -1123,7 +1123,7 @@ kernelcheck() { sestatus=$? if [[ ${sestatus} == 0 ]]; then echo_message "\033[31mDisabled\033[m\n" "Disabled,," " 0: results[case] = False @@ -308,9 +316,6 @@ def transaction_chain(zcash): results = {} # Generate the various addresses we will use - sprout_zaddr_1 = run_cmd(results, '3a', zcash, 'z_getnewaddress', ['sprout']) - sprout_zaddr_2 = run_cmd(results, '3b', zcash, 'z_getnewaddress', ['sprout']) - sprout_zaddr_3 = run_cmd(results, '3b', zcash, 'z_getnewaddress', ['sprout']) taddr_1 = run_cmd(results, '3c', zcash, 'getnewaddress') taddr_2 = run_cmd(results, '3d', zcash, 'getnewaddress') taddr_3 = run_cmd(results, '3d', zcash, 'getnewaddress') @@ -322,17 +327,11 @@ def transaction_chain(zcash): # Check that the zaddrs are all listed zaddrs = run_cmd(results, '5a', zcash, 'z_listaddresses') - if (sprout_zaddr_1 not in zaddrs or - sprout_zaddr_2 not in zaddrs or - sapling_zaddr_1 not in zaddrs or + if ( sapling_zaddr_1 not in zaddrs or sapling_zaddr_2 not in zaddrs): results['5a'] = False # Validate the addresses - ret = run_cmd(results, '5b', zcash, 'z_validateaddress', [sprout_zaddr_1]) - if not ret['isvalid'] or ret['type'] != 'sprout': - results['5b'] = False - ret = run_cmd(results, '5c', zcash, 'z_validateaddress', [sapling_zaddr_1]) if not ret['isvalid'] or ret['type'] != 'sapling': results['5c'] = False @@ -345,7 +344,7 @@ def transaction_chain(zcash): if zcash.use_faucet: print('Tapping the testnet faucet for testing funds...') chain_end = get_zfaucet_taddr() - tap_zfaucet(sprout_zaddr_1) + tap_zfaucet(taddr_1) print('Done! Leftover funds will be sent back to the faucet.') else: chain_end = input('Type or paste transparent address where leftover funds should be sent: ') @@ -354,14 +353,14 @@ def transaction_chain(zcash): return results print() print('Please send at least 0.01 ZEC/TAZ to the following address:') - print(sprout_zaddr_1) + print(taddr_1) print() input('Press Enter once the funds have been sent.') print() # Wait to receive starting balance - sprout_balance = wait_for_balance(zcash, sprout_zaddr_1) - starting_balance = sprout_balance + taddr_balance = wait_for_balance(zcash, taddr_1) + starting_balance = taddr_balance # # Start the transaction chain! @@ -372,19 +371,6 @@ def transaction_chain(zcash): print('#') print() try: - # - # First, split the funds across all three pools - # - - # Sprout -> taddr - taddr_balance = check_z_sendmany( - results, '4c', zcash, sprout_zaddr_1, [(taddr_1, (starting_balance / Decimal('10')) * Decimal('6'))])[0] - sprout_balance -= taddr_balance + DEFAULT_FEE - - balance = Decimal(run_cmd(results, '5f', zcash, 'z_getbalance', [sprout_zaddr_1])).quantize(Decimal('1.00000000')) - if balance != sprout_balance: - results['5f'] = False - # taddr -> Sapling # Send it all here because z_sendmany pick a new t-addr for change sapling_balance = check_z_sendmany( @@ -400,30 +386,20 @@ def transaction_chain(zcash): # Intra-pool tests # - # Sprout -> same Sprout # Sapling -> same Sapling - (sprout_balance, sapling_balance) = check_z_sendmany_parallel(results, zcash, [ - ('4a', sprout_zaddr_1, [(sprout_zaddr_1, sprout_balance - DEFAULT_FEE)]), - ('4g', sapling_zaddr_1, [(sapling_zaddr_1, sapling_balance - DEFAULT_FEE)]), - ]) + sapling_balance = check_z_sendmany( + results, '4g',zcash, sapling_zaddr_1, [(sapling_zaddr_1, sapling_balance - DEFAULT_FEE)])[0] - # Sprout -> different Sprout # taddr -> different taddr # Sapling -> different Sapling - (sprout_balance, taddr_balance, sapling_balance) = check_z_sendmany_parallel(results, zcash, [ - ('4b', sprout_zaddr_1, [(sprout_zaddr_2, sprout_balance - DEFAULT_FEE)]), + (taddr_balance, sapling_balance) = check_z_sendmany_parallel(results, zcash, [ ('4e', taddr_1, [(taddr_2, taddr_balance - DEFAULT_FEE)]), ('4h', sapling_zaddr_1, [(sapling_zaddr_2, sapling_balance - DEFAULT_FEE)]), ]) - # Sprout -> multiple Sprout # taddr -> multiple taddr # Sapling -> multiple Sapling check_z_sendmany_parallel(results, zcash, [ - ('4k', sprout_zaddr_2, [ - (sprout_zaddr_1, starting_balance / Decimal('10')), - (sprout_zaddr_3, starting_balance / Decimal('10')), - ]), ('4p', taddr_2, [ (taddr_1, starting_balance / Decimal('10')), (taddr_3, taddr_balance - (starting_balance / Decimal('10')) - DEFAULT_FEE), @@ -433,195 +409,75 @@ def transaction_chain(zcash): (sapling_zaddr_3, starting_balance / Decimal('10')), ]), ]) - sprout_balance -= DEFAULT_FEE + taddr_balance -= DEFAULT_FEE sapling_balance -= DEFAULT_FEE - # multiple Sprout -> Sprout # multiple Sapling -> Sapling # multiple taddr -> taddr check_z_mergetoaddress_parallel(results, zcash, [ - ('4ff', [sprout_zaddr_1, sprout_zaddr_3], sprout_zaddr_2, sprout_balance - DEFAULT_FEE), ('4gg', [sapling_zaddr_1, sapling_zaddr_3], sapling_zaddr_2, sapling_balance - DEFAULT_FEE), ('', [taddr_1, taddr_3], taddr_2, taddr_balance - DEFAULT_FEE), ]) - sprout_balance -= DEFAULT_FEE sapling_balance -= DEFAULT_FEE taddr_balance -= DEFAULT_FEE - # - # Now test a bunch of failing cases - # - - # Sprout -> Sapling - txid = z_sendmany(results, '4j', zcash, sprout_zaddr_2, [(sapling_zaddr_1, sprout_balance - DEFAULT_FEE)]) - if txid is not None: - print('Should have failed') - return results - - # Sprout -> taddr and Sapling - txid = z_sendmany(results, '4n', zcash, sprout_zaddr_2, [ - (taddr_2, starting_balance / Decimal('10')), - (sapling_zaddr_1, starting_balance / Decimal('10')), - ]) - if txid is not None: - print('Should have failed') - return results - - # Sprout -> multiple Sapling - txid = z_sendmany(results, '4o', zcash, sprout_zaddr_2, [ - (sapling_zaddr_1, starting_balance / Decimal('10')), - (sapling_zaddr_2, starting_balance / Decimal('10')), - ]) - if txid is not None: - print('Should have failed') - return results - - # taddr -> Sprout and Sapling - txid = z_sendmany(results, '4s', zcash, taddr_2, [ - (sprout_zaddr_1, starting_balance / Decimal('10')), - (sapling_zaddr_1, starting_balance / Decimal('10')), - ]) - if txid is not None: - print('Should have failed') - return results - - # Sapling -> multiple Sprout - txid = z_sendmany(results, '4u', zcash, sapling_zaddr_2, [ - (sprout_zaddr_1, starting_balance / Decimal('10')), - (sprout_zaddr_2, starting_balance / Decimal('10')), - ]) - if txid is not None: - print('Should have failed') - return results - - # Sapling -> Sapling and Sprout - txid = z_sendmany(results, '4x', zcash, sapling_zaddr_2, [ - (sapling_zaddr_1, starting_balance / Decimal('10')), - (sprout_zaddr_1, starting_balance / Decimal('10')), - ]) - if txid is not None: - print('Should have failed') - return results - - # multiple same taddr -> Sprout - txid = z_mergetoaddress(results, '4aa', zcash, [taddr_2, taddr_2], sprout_zaddr_2) - if txid is not None: - print('Should have failed') - return results - # # Inter-pool tests # - # Sprout -> taddr and Sprout # Sapling -> taddr and Sapling - check_z_sendmany_parallel(results, zcash, [ - ('4m', sprout_zaddr_2, [ - (taddr_1, starting_balance / Decimal('10')), - (sprout_zaddr_1, starting_balance / Decimal('10')), - ]), - ('4w', sapling_zaddr_2, [ + check_z_sendmany( + results, '4w', zcash, sapling_zaddr_2,[ (taddr_3, starting_balance / Decimal('10')), - (sapling_zaddr_1, starting_balance / Decimal('10')), - ]), - ]) - sprout_balance -= (starting_balance / Decimal('10')) + DEFAULT_FEE + (sapling_zaddr_1, starting_balance / Decimal('10'))])[0] + sapling_balance -= (starting_balance / Decimal('10')) + DEFAULT_FEE - taddr_balance += (starting_balance / Decimal('10')) * Decimal('2') + taddr_balance += starting_balance / Decimal('10') - # taddr and Sprout -> Sprout # taddr and Sapling -> Sapling - check_z_mergetoaddress_parallel(results, zcash, [ - ('4dd', [taddr_1, sprout_zaddr_1], sprout_zaddr_2, sprout_balance + (starting_balance / Decimal('10')) - DEFAULT_FEE), - ('4ee', [taddr_3, sapling_zaddr_1], sapling_zaddr_2, sapling_balance + (starting_balance / Decimal('10')) - DEFAULT_FEE), - ]) - sprout_balance += (starting_balance / Decimal('10')) - DEFAULT_FEE + check_z_mergetoaddress(results, '4ee', zcash, [taddr_3, sapling_zaddr_1], sapling_zaddr_2, sapling_balance + (starting_balance / Decimal('10')) - DEFAULT_FEE) + sapling_balance += (starting_balance / Decimal('10')) - DEFAULT_FEE - taddr_balance -= (starting_balance / Decimal('10')) * Decimal('2') + taddr_balance -= starting_balance / Decimal('10') - # Sprout -> multiple taddr # Sapling -> multiple taddr - check_z_sendmany_parallel(results, zcash, [ - ('4l', sprout_zaddr_2, [ - (taddr_1, (starting_balance / Decimal('10'))), - (taddr_3, (starting_balance / Decimal('10'))), - ]), - ('4v', sapling_zaddr_2, [ + check_z_sendmany(results, '4v', zcash, sapling_zaddr_2, [ (taddr_4, (starting_balance / Decimal('10'))), - (taddr_5, (starting_balance / Decimal('10'))), - ]), - ]) - sprout_balance -= ((starting_balance / Decimal('10')) * Decimal('2')) + DEFAULT_FEE + (taddr_5, (starting_balance / Decimal('10')))])[0] + sapling_balance -= ((starting_balance / Decimal('10')) * Decimal('2')) + DEFAULT_FEE - taddr_balance += (starting_balance / Decimal('10')) * Decimal('4') + taddr_balance += (starting_balance / Decimal('10')) * Decimal('2') - # multiple taddr -> Sprout # multiple taddr -> Sapling - check_z_mergetoaddress_parallel(results, zcash, [ - ('4z', [taddr_1, taddr_3], sprout_zaddr_2, sprout_balance + ((starting_balance / Decimal('10')) * Decimal('2')) - DEFAULT_FEE), - ('4bb', [taddr_4, taddr_5], sapling_zaddr_2, sapling_balance + ((starting_balance / Decimal('10')) * Decimal('2')) - DEFAULT_FEE), - ]) - sprout_balance += ((starting_balance / Decimal('10')) * Decimal('2')) - DEFAULT_FEE + check_z_mergetoaddress(results, '4bb',zcash, [taddr_4, taddr_5], sapling_zaddr_2, sapling_balance + ((starting_balance / Decimal('10')) * Decimal('2')) - DEFAULT_FEE) sapling_balance += ((starting_balance / Decimal('10')) * Decimal('2')) - DEFAULT_FEE - taddr_balance -= (starting_balance / Decimal('10')) * Decimal('4') - - # taddr -> Sprout - check_z_sendmany_parallel(results, zcash, [ - ('4d', taddr_2, [(sprout_zaddr_3, taddr_balance - DEFAULT_FEE)]), - ]) - sprout_balance += taddr_balance - DEFAULT_FEE - taddr_balance = Decimal('0') + taddr_balance -= (starting_balance / Decimal('10')) * Decimal('2') - # multiple Sprout -> taddr # multiple Sapling -> taddr - check_z_mergetoaddress_parallel(None, zcash, [ - ('', [sprout_zaddr_1, sprout_zaddr_2, sprout_zaddr_3], taddr_1, sprout_balance - DEFAULT_FEE), - ('', [sapling_zaddr_1, sapling_zaddr_2, sapling_zaddr_3], taddr_2, sapling_balance - DEFAULT_FEE), - ]) - taddr_balance = sprout_balance + sapling_balance - (2 * DEFAULT_FEE) - sprout_balance = Decimal('0') + check_z_mergetoaddress(None, '', zcash, [sapling_zaddr_1, sapling_zaddr_2, sapling_zaddr_3], taddr_2, sapling_balance - DEFAULT_FEE) + taddr_balance += sapling_balance - DEFAULT_FEE sapling_balance = Decimal('0') - # taddr -> multiple Sprout # taddr -> multiple Sapling - taddr_1_balance = Decimal(zcash.z_getbalance(taddr_1)).quantize(Decimal('1.00000000')) taddr_2_balance = Decimal(zcash.z_getbalance(taddr_2)).quantize(Decimal('1.00000000')) - check_z_sendmany_parallel(results, zcash, [ - ('4q', taddr_1, [ - (sprout_zaddr_1, (starting_balance / Decimal('10'))), - (sprout_zaddr_2, taddr_1_balance - (starting_balance / Decimal('10')) - DEFAULT_FEE), - ]), - ('4r', taddr_2, [ + check_z_sendmany(results, '4r', zcash, taddr_2, [ (sapling_zaddr_1, (starting_balance / Decimal('10'))), - (sapling_zaddr_2, taddr_2_balance - (starting_balance / Decimal('10')) - DEFAULT_FEE), - ]), - ]) - sprout_balance = taddr_1_balance - DEFAULT_FEE + (sapling_zaddr_2, taddr_2_balance - (starting_balance / Decimal('10')) - DEFAULT_FEE)])[0] + sapling_balance = taddr_2_balance - DEFAULT_FEE - taddr_balance = Decimal('0') + taddr_balance -= taddr_2_balance - # multiple Sprout -> taddr # multiple Sapling -> taddr - check_z_mergetoaddress_parallel(None, zcash, [ - ('', [sprout_zaddr_1, sprout_zaddr_2], taddr_1, sprout_balance - DEFAULT_FEE), - ('', [sapling_zaddr_1, sapling_zaddr_2], taddr_2, sapling_balance - DEFAULT_FEE), - ]) - taddr_balance = sprout_balance + sapling_balance - (Decimal('2') * DEFAULT_FEE) - sprout_balance = Decimal('0') + check_z_mergetoaddress(None, '', zcash, [sapling_zaddr_1, sapling_zaddr_2], taddr_2, sapling_balance - DEFAULT_FEE) + taddr_balance += sapling_balance - DEFAULT_FEE sapling_balance = Decimal('0') - # z_mergetoaddress taddr -> Sprout # z_mergetoaddress taddr -> Sapling - taddr_1_balance = Decimal(zcash.z_getbalance(taddr_1)).quantize(Decimal('1.00000000')) taddr_2_balance = Decimal(zcash.z_getbalance(taddr_2)).quantize(Decimal('1.00000000')) - check_z_mergetoaddress_parallel(results, zcash, [ - ('4y', [taddr_1], sprout_zaddr_1, taddr_1_balance - DEFAULT_FEE), - ('4cc', [taddr_2], sapling_zaddr_1, taddr_2_balance - DEFAULT_FEE), - ]) - sprout_balance = taddr_1_balance - DEFAULT_FEE + check_z_mergetoaddress(results, '4cc', zcash, [taddr_2], sapling_zaddr_1, taddr_2_balance - DEFAULT_FEE) sapling_balance = taddr_2_balance - DEFAULT_FEE - taddr_balance = Decimal('0') + taddr_balance -= taddr_2_balance except Exception as e: print('Error: %s' % e) traceback.print_exc() @@ -634,7 +490,6 @@ def transaction_chain(zcash): print('# Finishing transaction chain') print('#') all_addrs = [ - sprout_zaddr_1, sprout_zaddr_2, sprout_zaddr_3, taddr_1, taddr_2, taddr_3, taddr_4, taddr_5, sapling_zaddr_1, sapling_zaddr_2, sapling_zaddr_3, ] diff --git a/rust-toolchain b/rust-toolchain index b7921ae87bc..bb120e876c6 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.54.0 +1.59.0 diff --git a/src/Makefile.am b/src/Makefile.am index 5f4ee7270c4..a8824b4e8d0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,9 @@ LIBSECP256K1=secp256k1/libsecp256k1.la LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a +WALLET_TOOL_BIN=zcashd-wallet-tool$(EXEEXT) +WALLET_TOOL_BUILD=$(top_builddir)/target/$(RUST_TARGET)/release/zcashd-wallet-tool$(EXEEXT) + if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a endif @@ -39,8 +42,15 @@ if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a endif -RUST_ENV_VARS = RUSTC="$(RUSTC)" TERM=dumb -RUST_BUILD_OPTS = --lib --release --target $(RUST_TARGET) +# We depend on the secp256k1 crate for some logic on the Rust side of the FFI. This crate +# is a wrapper around libsecp256k1, which we already vendor in our code; the crate vendors +# its own copy with non-colliding symbols. To ensure that we only use a single version of +# libsecp256k1, we disable symbol renaming in the secp256k1-sys crate so it links to the +# same library as the C++ code. +# - Note that this does not prevent the secp256k1-sys vendored code from being built; this +# requires https://github.com/rust-bitcoin/rust-secp256k1/issues/380 to be addressed. +RUST_ENV_VARS = RUSTC="$(RUSTC)" TERM=dumb RUSTFLAGS="--cfg=rust_secp_no_symbol_renaming" +RUST_BUILD_OPTS = --release --target $(RUST_TARGET) --manifest-path $(top_srcdir)/Cargo.toml rust_verbose = $(rust_verbose_@AM_V@) rust_verbose_ = $(rust_verbose_@AM_DEFAULT_V@) @@ -65,10 +75,16 @@ $(CARGO_CONFIGURED): $(top_srcdir)/.cargo/config.offline $(AM_V_at)touch $@ endif -cargo-build: $(CARGO_CONFIGURED) - $(RUST_ENV_VARS) $(CARGO) build $(RUST_BUILD_OPTS) $(rust_verbose) --manifest-path $(top_srcdir)/Cargo.toml +cargo-build-lib: $(CARGO_CONFIGURED) + $(RUST_ENV_VARS) $(CARGO) build --lib $(RUST_BUILD_OPTS) $(rust_verbose) + +cargo-build-bins: $(CARGO_CONFIGURED) + $(RUST_ENV_VARS) $(CARGO) build --bins $(RUST_BUILD_OPTS) $(rust_verbose) -$(LIBRUSTZCASH): cargo-build +$(WALLET_TOOL_BIN): cargo-build-bins + $(AM_V_at)cp $(WALLET_TOOL_BUILD) $@ + +$(LIBRUSTZCASH): cargo-build-lib $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) @@ -92,6 +108,7 @@ lib_LTLIBRARIES = $(LIBZCASH_SCRIPT) bin_PROGRAMS = noinst_PROGRAMS = +bin_SCRIPTS = TESTS = BENCHMARKS = @@ -101,14 +118,19 @@ endif if BUILD_BITCOIN_UTILS bin_PROGRAMS += zcash-cli zcash-tx + bin_SCRIPTS += $(WALLET_TOOL_BIN) endif LIBZCASH_H = \ zcash/IncrementalMerkleTree.hpp \ zcash/NoteEncryption.hpp \ zcash/Address.hpp \ + zcash/address/transparent.h \ + zcash/address/mnemonic.h \ + zcash/address/orchard.hpp \ zcash/address/sapling.hpp \ zcash/address/sprout.hpp \ + zcash/address/unified.h \ zcash/address/zip32.h \ zcash/History.hpp \ zcash/JoinSplit.hpp \ @@ -118,7 +140,7 @@ LIBZCASH_H = \ zcash/util.h \ zcash/Zcash.h -.PHONY: FORCE cargo-build check-symbols check-security +.PHONY: FORCE cargo-build-lib cargo-build-bins check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addrdb.h \ @@ -180,6 +202,7 @@ BITCOIN_CORE_H = \ pow.h \ prevector.h \ primitives/block.h \ + primitives/orchard.h \ primitives/transaction.h \ proof_verifier.h \ protocol.h \ @@ -222,6 +245,7 @@ BITCOIN_CORE_H = \ uint252.h \ undo.h \ util.h \ + util/match.h \ utilmoneystr.h \ utilstrencodings.h \ utiltest.h \ @@ -322,6 +346,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/asyncrpcoperation_shieldcoinbase.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ + wallet/orchard.cpp \ wallet/paymentdisclosure.cpp \ wallet/paymentdisclosuredb.cpp \ wallet/rpcdisclosure.cpp \ @@ -392,6 +417,7 @@ libbitcoin_common_a_SOURCES = \ netbase.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ + primitives/tx_version_info.cpp \ proof_verifier.cpp \ protocol.cpp \ pubkey.cpp \ @@ -501,6 +527,7 @@ zcash_cli_LDADD = \ $(LIBZCASH) \ $(LIBRUSTZCASH) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBSECP256K1) \ $(LIBZCASH_LIBS) # @@ -533,8 +560,12 @@ libzcash_a_SOURCES = \ zcash/IncrementalMerkleTree.cpp \ zcash/NoteEncryption.cpp \ zcash/Address.cpp \ + zcash/address/transparent.cpp \ + zcash/address/mnemonic.cpp \ + zcash/address/orchard.cpp \ zcash/address/sapling.cpp \ zcash/address/sprout.cpp \ + zcash/address/unified.cpp \ zcash/address/zip32.cpp \ zcash/History.cpp \ zcash/JoinSplit.cpp \ @@ -557,6 +588,7 @@ libzcash_script_la_SOURCES = \ crypto/sha512.cpp \ hash.cpp \ primitives/transaction.cpp \ + primitives/tx_version_info.cpp \ pubkey.cpp \ script/zcash_script.cpp \ script/interpreter.cpp \ @@ -582,7 +614,7 @@ CTAES_DIST += crypto/ctaes/ctaes.h CTAES_DIST += crypto/ctaes/README.md CTAES_DIST += crypto/ctaes/test.c -CLEANFILES = *.gcda *.gcno */*.gcno wallet/*/*.gcno +CLEANFILES = *.gcda *.gcno */*.gcno wallet/*/*.gcno $(bin_SCRIPTS) DISTCLEANFILES = obj/build.h @@ -606,16 +638,17 @@ clean-local: $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) -c -o $@ $< -check-symbols: $(bin_PROGRAMS) +check-symbols: $(bin_PROGRAMS) $(bin_SCRIPTS) if GLIBC_BACK_COMPAT - @echo "Checking glibc back compat of [$(bin_PROGRAMS)]..." - $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS) + @echo "Checking glibc back compat of [$(bin_PROGRAMS) $(bin_SCRIPTS)]..." + $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS) $(bin_SCRIPTS) endif -check-security: $(bin_PROGRAMS) +check-security: $(bin_PROGRAMS) $(bin_SCRIPTS) if HARDEN - @echo "Checking binary security of [$(bin_PROGRAMS)]..." + @echo "Checking binary security of [$(bin_PROGRAMS) $(bin_SCRIPTS)]..." $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py $(bin_PROGRAMS) + $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py --allow-no-canary $(bin_SCRIPTS) endif %.pb.cc %.pb.h: %.proto diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 1cda367e22b..4db48496078 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -21,9 +21,11 @@ zcash_gtest_SOURCES = \ # depend on global state (see #1539) if ENABLE_WALLET zcash_gtest_SOURCES += \ - wallet/gtest/test_wallet_zkeys.cpp + wallet/gtest/test_wallet_zkeys.cpp \ + wallet/gtest/test_orchard_zkeys.cpp endif zcash_gtest_SOURCES += \ + test/data/merkle_roots_orchard.h \ gtest/test_tautology.cpp \ gtest/test_allocator.cpp \ gtest/test_checkblock.cpp \ @@ -57,6 +59,8 @@ zcash_gtest_SOURCES += \ gtest/test_zip32.cpp if ENABLE_WALLET zcash_gtest_SOURCES += \ + wallet/gtest/test_note_selection.cpp \ + wallet/gtest/test_orchard_wallet.cpp \ wallet/gtest/test_paymentdisclosure.cpp \ wallet/gtest/test_wallet.cpp endif diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8f86ec3bae1..a21b7e403ab 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -44,6 +44,7 @@ JSON_TEST_FILES = \ test/data/merkle_commitments_sapling.json \ test/data/sapling_key_components.json \ test/data/unified_addrs.json \ + test/data/unified_full_viewing_keys.json \ test/data/zip0244.json RAW_TEST_FILES = test/data/alertTests.raw diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp index 61b9d5be713..fdc2cb6926d 100644 --- a/src/bench/perf.cpp +++ b/src/bench/perf.cpp @@ -6,7 +6,7 @@ #if defined(__i386__) || defined(__x86_64__) -/* These architectures support quering the cycle counter +/* These architectures support querying the cycle counter * from user space, no need for any syscall overhead. */ void perf_init(void) { } diff --git a/src/bench/verification.cpp b/src/bench/verification.cpp index ba7aea1c2e1..19c0b27d996 100644 --- a/src/bench/verification.cpp +++ b/src/bench/verification.cpp @@ -25,8 +25,7 @@ static void ECDSA(benchmark::State& state) mtx.nVersion = SAPLING_TX_VERSION; mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; - CKey key; - key.MakeNewKey(false); + CKey key = CKey::TestOnlyRandomKey(false); CBasicKeyStore keystore; keystore.AddKeyPubKey(key, key.GetPubKey()); CKeyID hash = key.GetPubKey().GetID(); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 0d9492c52fb..b78fb5461c4 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -39,7 +39,7 @@ std::string HelpMessageCli() strUsage += HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("This help message")); strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); - strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); + strUsage += HelpMessageOpt("-datadir=", _("Specify data directory (this path cannot use '~')")); strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). If first extra argument is `walletpassphrase` then the first line(password) will not be echoed.")); AppendParamsHelpMessages(strUsage); strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), DEFAULT_RPCCONNECT)); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 17ce1ebd548..7eccc84bf44 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -52,7 +52,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi * transaction cannot be spent since it did not originally exist in the * database (and is in any case of zero value). * - * >>> from pyblake2 import blake2s + * >>> from hashlib import blake2s * >>> 'Zcash' + blake2s(b'The Economist 2016-10-29 Known unknown: Another crypto-currency is born. BTC#436254 0000000000000000044f321997f336d2908cf8c8d6893e88dbf067e2d949487d ETH#2521903 483039a6b6bd8bd05f0584f9a078d075e454925eb71c1f13eaff59b405a721bb DJIA close on 27 Oct 2016: 18,169.68').hexdigest() * * CBlock(hash=00040fe8, ver=4, hashPrevBlock=00000000000000, hashMerkleRoot=c4eaa5, nTime=1477641360, nBits=1f07ffff, nNonce=4695, vtx=1) @@ -86,7 +86,7 @@ class CMainParams : public CChainParams { CMainParams() { keyConstants.strNetworkID = "main"; strCurrencyUnits = "ZEC"; - bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md + keyConstants.bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md consensus.fCoinbaseMustBeShielded = true; consensus.nSubsidySlowStartInterval = 20000; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; @@ -133,7 +133,7 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight = 1046400; consensus.vUpgrades[Consensus::UPGRADE_CANOPY].hashActivationBlock = uint256S("00000000002038016f976744c369dce7419fca30e7171dfac703af5e5f7ad1d4"); - consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170015; + consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170017; consensus.vUpgrades[Consensus::UPGRADE_NU5].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nProtocolVersion = 0x7FFFFFFF; @@ -370,7 +370,7 @@ class CTestNetParams : public CChainParams { CTestNetParams() { keyConstants.strNetworkID = "test"; strCurrencyUnits = "TAZ"; - bip44CoinType = 1; + keyConstants.bip44CoinType = 1; consensus.fCoinbaseMustBeShielded = true; consensus.nSubsidySlowStartInterval = 20000; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; @@ -417,9 +417,8 @@ class CTestNetParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight = 1028500; consensus.vUpgrades[Consensus::UPGRADE_CANOPY].hashActivationBlock = uint256S("01a4d7c6aada30c87762c1bf33fff5df7266b1fd7616bfdb5227fa59bd79e7a2"); - consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170014; - consensus.vUpgrades[Consensus::UPGRADE_NU5].nActivationHeight = - Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170015; + consensus.vUpgrades[Consensus::UPGRADE_NU5].nActivationHeight = 1599200; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nProtocolVersion = 0x7FFFFFFF; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; @@ -622,7 +621,7 @@ class CRegTestParams : public CChainParams { CRegTestParams() { keyConstants.strNetworkID = "regtest"; strCurrencyUnits = "REG"; - bip44CoinType = 1; + keyConstants.bip44CoinType = 1; consensus.fCoinbaseMustBeShielded = false; consensus.nSubsidySlowStartInterval = 0; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL; @@ -634,7 +633,7 @@ class CRegTestParams : public CChainParams { static_assert(equihash_parameters_acceptable(N, K)); consensus.nEquihashN = N; consensus.nEquihashK = K; - consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); + consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); // if this is any larger, the for loop in GetNextWorkRequired can overflow bnTot consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down @@ -664,7 +663,7 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nProtocolVersion = 170012; consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170014; + consensus.vUpgrades[Consensus::UPGRADE_NU5].nProtocolVersion = 170015; consensus.vUpgrades[Consensus::UPGRADE_NU5].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nProtocolVersion = 0x7FFFFFFF; @@ -730,6 +729,9 @@ class CRegTestParams : public CChainParams { // Founders reward script expects a vector of 2-of-3 multisig addresses vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" }; assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight(0)); + + // do not require the wallet backup to be confirmed in regtest mode + fRequireWalletBackup = false; } void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight) @@ -823,10 +825,10 @@ CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const { assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight(nHeight)); KeyIO keyIO(*this); - CTxDestination address = keyIO.DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str()); - assert(IsValidDestination(address)); - assert(IsScriptDestination(address)); - CScriptID scriptID = std::get(address); // address is a variant + auto address = keyIO.DecodePaymentAddress(GetFoundersRewardAddressAtHeight(nHeight).c_str()); + assert(address.has_value()); + assert(std::holds_alternative(address.value())); + CScriptID scriptID = std::get(address.value()); CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return script; } diff --git a/src/chainparams.h b/src/chainparams.h index cf106277852..4b04ac967dc 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -32,17 +32,6 @@ struct CCheckpointData { double fTransactionsPerDay; }; -class CBaseKeyConstants : public KeyConstants { -public: - std::string NetworkIDString() const { return strNetworkID; } - const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } - const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; } - - std::string strNetworkID; - std::vector base58Prefixes[KeyConstants::MAX_BASE58_TYPES]; - std::string bech32HRPs[KeyConstants::MAX_BECH32_TYPES]; -}; - /** * CChainParams defines various tweakable parameters of a given instance of the * Bitcoin system. There are three: the main network on which people trade goods @@ -50,7 +39,7 @@ class CBaseKeyConstants : public KeyConstants { * a regression test mode which is intended for private networks only. It has * minimal difficulty to ensure that blocks can be found instantly. */ -class CChainParams: public KeyConstants +class CChainParams: public KeyConstants { public: const Consensus::Params& GetConsensus() const { return consensus; } @@ -62,6 +51,7 @@ class CChainParams: public KeyConstants CAmount SproutValuePoolCheckpointBalance() const { return nSproutValuePoolCheckpointBalance; } uint256 SproutValuePoolCheckpointBlockHash() const { return hashSproutValuePoolCheckpointBlock; } bool ZIP209Enabled() const { return fZIP209Enabled; } + bool RequireWalletBackup() const { return fRequireWalletBackup; } const CBlock& GenesisBlock() const { return genesis; } /** Make miner wait to have peers to avoid wasting work */ @@ -72,19 +62,24 @@ class CChainParams: public KeyConstants bool RequireStandard() const { return fRequireStandard; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } std::string CurrencyUnits() const { return strCurrencyUnits; } - uint32_t BIP44CoinType() const { return bip44CoinType; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } /** In the future use NetworkIDString() for RPC fields */ bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; } - /** Return the BIP70 network string (main, test or regtest) */ - std::string NetworkIDString() const { return keyConstants.NetworkIDString(); } const std::vector& DNSSeeds() const { return vSeeds; } - const std::vector& Base58Prefix(Base58Type type) const { - return keyConstants.Base58Prefix(type); + /** Return the BIP70 network string (main, test or regtest) */ + std::string NetworkIDString() const { + return keyConstants.NetworkIDString(); + } + /** Return the BIP44 coin type for addresses created by the zcashd embedded wallet. */ + uint32_t BIP44CoinType() const { + return keyConstants.BIP44CoinType(); + } + const std::vector& Base58Prefix(Base58Type type) const { + return keyConstants.Base58Prefix(type); } - const std::string& Bech32HRP(Bech32Type type) const { - return keyConstants.Bech32HRP(type); + const std::string& Bech32HRP(Bech32Type type) const { + return keyConstants.Bech32HRP(type); } const std::vector& FixedSeeds() const { return vFixedSeeds; } const CCheckpointData& Checkpoints() const { return checkpointData; } @@ -106,7 +101,6 @@ class CChainParams: public KeyConstants std::vector vSeeds; CBaseKeyConstants keyConstants; std::string strCurrencyUnits; - uint32_t bip44CoinType; CBlock genesis; std::vector vFixedSeeds; bool fMiningRequiresPeers = false; @@ -121,6 +115,7 @@ class CChainParams: public KeyConstants CAmount nSproutValuePoolCheckpointBalance = 0; uint256 hashSproutValuePoolCheckpointBlock; bool fZIP209Enabled = false; + bool fRequireWalletBackup = true; }; /** diff --git a/src/clientversion.h b/src/clientversion.h index 7a8e56902cb..ccb4acdd659 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers -// Copyright (c) 2016-2021 The Zcash developers +// Copyright (c) 2016-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -16,9 +16,9 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 4 -#define CLIENT_VERSION_MINOR 4 -#define CLIENT_VERSION_REVISION 1 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_MINOR 6 +#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_BUILD 51 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true @@ -27,7 +27,7 @@ * Copyright year (2009-this) * Todo: update this when changing our copyright comments in the source */ -#define COPYRIGHT_YEAR 2021 +#define COPYRIGHT_YEAR 2022 #endif //HAVE_CONFIG_H diff --git a/src/coins.cpp b/src/coins.cpp index 0ea164cdcd3..4ed2907afca 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -46,7 +46,7 @@ bool CCoins::Spend(uint32_t nPos) } bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return false; } bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return false; } -bool CCoinsView::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const { return false; } +bool CCoinsView::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const { return false; } bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return false; } bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } @@ -75,7 +75,7 @@ CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); } bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); } -bool CCoinsViewBacked::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const { return base->GetOrchardAnchorAt(rt, tree); } +bool CCoinsViewBacked::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const { return base->GetOrchardAnchorAt(rt, tree); } bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); } bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -191,7 +191,7 @@ bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &t return true; } -bool CCoinsViewCache::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const { +bool CCoinsViewCache::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const { CAnchorsOrchardMap::const_iterator it = cacheOrchardAnchors.find(rt); if (it != cacheOrchardAnchors.end()) { if (it->second.entered) { @@ -321,9 +321,9 @@ template<> void CCoinsViewCache::PushAnchor(const SaplingMerkleTree &tree) ); } -template<> void CCoinsViewCache::PushAnchor(const OrchardMerkleTree &tree) +template<> void CCoinsViewCache::PushAnchor(const OrchardMerkleFrontier &tree) { - AbstractPushAnchor( + AbstractPushAnchor( tree, ORCHARD, cacheOrchardAnchors, @@ -352,7 +352,7 @@ void CCoinsViewCache::BringBestAnchorIntoCache( template<> void CCoinsViewCache::BringBestAnchorIntoCache( const uint256 ¤tRoot, - OrchardMerkleTree &tree + OrchardMerkleFrontier &tree ) { assert(GetOrchardAnchorAt(currentRoot, tree)); @@ -683,6 +683,14 @@ void CCoinsViewCache::PopAnchor(const uint256 &newrt, ShieldedType type) { hashSaplingAnchor ); break; + case ORCHARD: + AbstractPopAnchor( + newrt, + ORCHARD, + cacheOrchardAnchors, + hashOrchardAnchor + ); + break; default: throw std::runtime_error("Unknown shielded type"); } @@ -1069,7 +1077,7 @@ std::optional CCoinsViewCache::HaveShieldedRequirements( std::optional root = tx.GetOrchardBundle().GetAnchor(); if (root) { - OrchardMerkleTree tree; + OrchardMerkleFrontier tree; if (!GetOrchardAnchorAt(root.value(), tree)) { auto txid = tx.GetHash().ToString(); auto anchor = root.value().ToString(); diff --git a/src/coins.h b/src/coins.h index ddfe08103c3..c318d65d3b5 100644 --- a/src/coins.h +++ b/src/coins.h @@ -304,7 +304,7 @@ struct CAnchorsSaplingCacheEntry struct CAnchorsOrchardCacheEntry { bool entered; // This will be false if the anchor is removed from the cache - OrchardMerkleTree tree; // The tree itself + OrchardMerkleFrontier tree; // The tree itself unsigned char flags; enum Flags { @@ -368,7 +368,7 @@ class CCoinsView virtual bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; //! Retrieve the tree (Orchard) at a particular anchored root in the chain - virtual bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const; + virtual bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const; //! Determine whether a nullifier is spent or not virtual bool GetNullifier(const uint256 &nullifier, ShieldedType type) const; @@ -428,7 +428,7 @@ class CCoinsViewBacked : public CCoinsView CCoinsViewBacked(CCoinsView *viewIn); bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; - bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const; + bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const; bool GetNullifier(const uint256 &nullifier, ShieldedType type) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; @@ -521,7 +521,7 @@ class CCoinsViewCache : public CCoinsViewBacked // Standard CCoinsView methods bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; - bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const; + bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const; bool GetNullifier(const uint256 &nullifier, ShieldedType type) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 2ced730e82c..7d348da4a4d 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -9,8 +9,18 @@ #include