diff --git a/Cargo.lock b/Cargo.lock index d14eea0073f..605b9360aba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "bridgetree" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62227647af796dd9f1637da0392676a2e200973b817b082fc9be89bf93ddd74" +checksum = "cef977c7f8e75aa81fc589064c121ab8d32448b7939d34d58df479aa93e65ea5" dependencies = [ "incrementalmerkletree", ] @@ -923,9 +923,9 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75346da3bd8e3d8891d02508245ed2df34447ca6637e343829f8d08986e9cde2" +checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df" dependencies = [ "either", "proptest", @@ -933,6 +933,16 @@ dependencies = [ "rand_core", ] +[[package]] +name = "incrementalmerkletree-testing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6959842a2ad15e423a7c39b77555039efdccf50a1a43cce43827fc2f881c27d2" +dependencies = [ + "incrementalmerkletree", + "proptest", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1344,9 +1354,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc7bde644aeb980be296cd908c6650894dc8541deb56f9f5294c52ed7ca568f" +checksum = "4f18e997fa121de5c73e95cdc7e8512ae43b7de38904aeea5e5713cc48f3c0ba" dependencies = [ "aes", "bitvec", @@ -1798,9 +1808,9 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e379398fffad84e49f9a45a05635fc004f66086e65942dbf4eb95332c26d2a" +checksum = "cfff8cfce16aeb38da50b8e2ed33c9018f30552beff2210c266662a021b17f38" dependencies = [ "aes", "bellman", @@ -2534,9 +2544,9 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bccd6cefb76f87b6d15a9e7b02b6c0515648c6de8e806c4e2d6f0f6ae640c5" +checksum = "4ff95eac82f71286a79c750e674550d64fb2b7aadaef7b89286b2917f645457d" dependencies = [ "bech32", "bs58", @@ -2581,9 +2591,9 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d87ab6a55591a8cf1866749fdc739ae1bbd06e6cec07ab0bbe5d57ee3390eb2" +checksum = "6ab47d526d7fd6f88b3a2854ad81b54757a80c2aeadd1d8b06f690556af9743c" dependencies = [ "aes", "bip32", @@ -2621,9 +2631,9 @@ dependencies = [ [[package]] name = "zcash_proofs" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9fc0032b3d90f000f50dba7a996ad6556b7dba5b5145f93ab67b6eb74d3a48" +checksum = "daba607872e60d91a09248d8e1ea3d6801c819fb80d67016d9de02d81323c10d" dependencies = [ "bellman", "blake2b_simd", @@ -2644,12 +2654,13 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1ff002bd41ba76b42d42a02ee11de06790b7fdbc904bdea4486b9a93b2a5e4" +checksum = "6bc22b9155b2c7eb20105cd06de170d188c1bc86489b92aa3fda7b8da8d96acf" dependencies = [ "document-features", "incrementalmerkletree", + "incrementalmerkletree-testing", "memuse", "proptest", ] diff --git a/Cargo.toml b/Cargo.toml index b1c17b25cb7..a6ca7f7ef17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,19 +39,19 @@ bip0039 = { version = "0.10.1", features = ["std", "all-languages"] } blake2b_simd = "1" blake2s_simd = "1" bls12_381 = "0.8" -bridgetree = "0.5" +bridgetree = "0.6" byteorder = "1" crossbeam-channel = "0.5" getrandom = "0.2" group = "0.13" hex = "0.4" -incrementalmerkletree = "0.6" +incrementalmerkletree = "0.7" libc = "0.2" jubjub = "0.10" memuse = "0.2" nonempty = "0.7" -orchard = "0.9" -sapling = { package = "sapling-crypto", version = "0.2", features = ["temporary-zcashd"] } +orchard = "0.10" +sapling = { package = "sapling-crypto", version = "0.3", features = ["temporary-zcashd"] } secp256k1 = "0.27" subtle = "2.2" rand_core = "0.6" @@ -59,13 +59,13 @@ redjubjub = "0.7" tracing = "0.1" tracing-core = "0.1" tracing-appender = "0.2" -zcash_address = "0.5" +zcash_address = "0.6" zcash_encoding = "0.2.1" zcash_history = "0.4" zcash_note_encryption = "0.4" -zcash_primitives = { version = "0.17", features = ["temporary-zcashd", "transparent-inputs"] } -zcash_proofs = { version = "0.17", features = ["directories"] } -zcash_protocol = { version = "0.3", features = ["local-consensus"] } +zcash_primitives = { version = "0.19", features = ["temporary-zcashd", "transparent-inputs"] } +zcash_proofs = { version = "0.19", features = ["directories"] } +zcash_protocol = { version = "0.4", features = ["local-consensus"] } ed25519-zebra = "4" zeroize = "1.4.2" wagyu-zcash-parameters = "0.2" @@ -98,9 +98,9 @@ thiserror = "1" time = { version = "0.3", features = ["formatting", "macros"] } [dev-dependencies] -incrementalmerkletree = { version = "0.6", features = ["test-dependencies"] } +incrementalmerkletree = { version = "0.7", features = ["test-dependencies"] } proptest = "1.0.0" -zcash_primitives = { version = "0.17", features = ["temporary-zcashd", "transparent-inputs", "test-dependencies"] } +zcash_primitives = { version = "0.19", features = ["temporary-zcashd", "transparent-inputs", "test-dependencies"] } [dependencies.tracing-subscriber] version = "0.3" diff --git a/README.md b/README.md index 72101ec4ea5..66c3eb9e9de 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 5.10.0 +Zcash 6.0.0 =========== diff --git a/code_of_conduct.md b/code_of_conduct.md index 07e751de779..0661386014c 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -47,13 +47,14 @@ is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. -You may send reports to [our Conduct email](mailto:conduct@z.cash). +You may send reports to [our Conduct email](mailto:conduct@electriccoin.co). If you wish to contact specific maintainers directly, the following have made themselves available for conduct issues: -- Daira Hopwood (daira at z.cash) -- Sean Bowe (sean at z.cash) +- Daira-Emma Hopwood (daira-emma at electriccoin.co) +- Kris Nuttycombe (kris at electriccoin.co) +- Jack Grigg (jack at electriccoin.co) This Code of Conduct is adapted from the [Contributor Covenant][homepage], diff --git a/configure.ac b/configure.ac index e5ee383a0d4..3a45d46757f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) -define(_CLIENT_VERSION_MAJOR, 5) -define(_CLIENT_VERSION_MINOR, 10) +define(_CLIENT_VERSION_MAJOR, 6) +define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 50) 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))) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 346f7a36baf..8ea0a87060e 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,15 @@ +zcash (6.0.0) stable; urgency=high + + * 6.0.0 release. + + -- Electric Coin Company Wed, 02 Oct 2024 20:45:09 +0000 + +zcash (6.0.0~rc1) stable; urgency=medium + + * 6.0.0-rc1 release. + + -- Electric Coin Company Fri, 27 Sep 2024 19:51:34 +0000 + zcash (5.10.0) stable; urgency=medium * 5.10.0 release. diff --git a/contrib/gitian-descriptors/gitian-linux-parallel.yml b/contrib/gitian-descriptors/gitian-linux-parallel.yml index 78eb0a1e0d3..ced83a7a1c5 100644 --- a/contrib/gitian-descriptors/gitian-linux-parallel.yml +++ b/contrib/gitian-descriptors/gitian-linux-parallel.yml @@ -1,5 +1,5 @@ --- -name: "zcash-5.10.0" +name: "zcash-6.0.0" enable_cache: true distro: "debian" suites: diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 044b3e33a5c..e0ab81a022e 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-5.10.0" +name: "zcash-6.0.0" enable_cache: true distro: "debian" suites: diff --git a/depends/packages/native_cmake.mk b/depends/packages/native_cmake.mk index 54fb9cb5453..84365de2e9e 100644 --- a/depends/packages/native_cmake.mk +++ b/depends/packages/native_cmake.mk @@ -1,8 +1,8 @@ package=native_cmake -$(package)_version=3.30.3 +$(package)_version=3.30.4 $(package)_download_path=https://github.com/Kitware/CMake/releases/download/v$($(package)_version) $(package)_file_name=cmake-$($(package)_version).tar.gz -$(package)_sha256_hash=6d5de15b6715091df7f5441007425264bdd477809f80333fdf95f846aaff88e4 +$(package)_sha256_hash=c759c97274f1e7aaaafcb1f0d261f9de9bf3a5d6ecb7e2df616324a46fe704b2 define $(package)_set_vars $(package)_config_opts += -DCMAKE_BUILD_TYPE:STRING=Release diff --git a/doc/authors.md b/doc/authors.md index 977adc2e67b..85b752f175f 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,9 +1,9 @@ Zcash Contributors ================== -* Jack Grigg (2157) -* Kris Nuttycombe (750) -* Daira-Emma Hopwood (483) +* Jack Grigg (2181) +* Kris Nuttycombe (751) +* Daira-Emma Hopwood (492) * Simon Liu (464) * Sean Bowe (413) * Eirik Ogilvie-Wigley (273) @@ -88,6 +88,7 @@ Zcash Contributors * Evan Klitzke (4) * DeckerSU (4) * Ben Woosley (4) +* y4ssi (3) * mruddy (3) * lpescher (3) * isle2983 (3) @@ -152,7 +153,6 @@ Zcash Contributors * Akio Nakamura (2) * ロハン ダル (1) * zathras-crypto (1) -* y4ssi (1) * vim88 (1) * user (1) * unsystemizer (1) diff --git a/doc/book/src/user/release-support.md b/doc/book/src/user/release-support.md index 4b95d87fe6e..52f62788950 100644 --- a/doc/book/src/user/release-support.md +++ b/doc/book/src/user/release-support.md @@ -42,8 +42,8 @@ time, and may shift due to changes in network solution power. | `zcashd` version | Release date | Halt height | End of Support | | ---------------- | ------------ | ----------- | -------------- | -| 5.9.1-rc1 | 2024-05-22 | 2643624 | 2024-09-11 | -| 5.9.1 | 2024-05-23 | 2644900 | 2024-09-12 | | 5.10.0-rc1 | 2024-08-22 | 2700600 | 2024-10-31 | | 5.10.0 | 2024-08-27 | 2706540 | 2024-11-05 | +| 6.0.0-rc1 | 2024-09-27 | 2710272 | 2024-11-08 | +| 6.0.0 | 2024-10-02 | 2796400 | 2025-01-22 | diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 0d1aac63f6c..d9878345d00 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.49.3. -.TH ZCASH-CLI "1" "August 2024" "zcash-cli v5.10.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH ZCASH-CLI "1" "October 2024" "zcash-cli v6.0.0" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v5.10.0 +zcash-cli \- manual page for zcash-cli v6.0.0 .SH DESCRIPTION -Zcash RPC client version v5.10.0 +Zcash RPC client version v6.0.0 .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 d45b998c8ac..cffaa517bc7 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.49.3. -.TH ZCASH-TX "1" "August 2024" "zcash-tx v5.10.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH ZCASH-TX "1" "October 2024" "zcash-tx v6.0.0" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v5.10.0 +zcash-tx \- manual page for zcash-tx v6.0.0 .SH DESCRIPTION -Zcash zcash\-tx utility version v5.10.0 +Zcash zcash\-tx utility version v6.0.0 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd-wallet-tool.1 b/doc/man/zcashd-wallet-tool.1 index 60df43dad85..54314e1d750 100644 --- a/doc/man/zcashd-wallet-tool.1 +++ b/doc/man/zcashd-wallet-tool.1 @@ -1,7 +1,7 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ZCASHD-WALLET-TOOL "1" "August 2024" "zcashd-wallet-tool v5.10.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH ZCASHD-WALLET-TOOL "1" "October 2024" "zcashd-wallet-tool v6.0.0" "User Commands" .SH NAME -zcashd-wallet-tool \- manual page for zcashd-wallet-tool v5.10.0 +zcashd-wallet-tool \- manual page for zcashd-wallet-tool v6.0.0 .SH SYNOPSIS .B zcashd-wallet-tool [\fI\,OPTIONS\/\fR] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 79a9ea0a446..9da9ecaf635 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.49.3. -.TH ZCASHD "1" "August 2024" "zcashd v5.10.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH ZCASHD "1" "October 2024" "zcashd v6.0.0" "User Commands" .SH NAME -zcashd \- manual page for zcashd v5.10.0 +zcashd \- manual page for zcashd v6.0.0 .SH DESCRIPTION -Zcash Daemon version v5.10.0 +Zcash Daemon version v6.0.0 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -484,7 +484,7 @@ Maximum size of data in data carrier transactions we relay and mine \fB\-txunpaidactionlimit=\fR .IP Transactions with more than this number of unpaid actions will not be -accepted to the mempool or relayed (default: 50) +accepted to the mempool or relayed (default: 0) .PP Block creation options: .HP @@ -495,7 +495,7 @@ Set maximum block size in bytes (default: 2000000) \fB\-blockunpaidactionlimit=\fR .IP Set the limit on unpaid actions that will be accepted in a block for -transactions paying less than the ZIP 317 fee (default: 50) +transactions paying less than the ZIP 317 fee (default: 0) .PP Mining options: .HP diff --git a/doc/release-notes/release-notes-6.0.0-rc1.md b/doc/release-notes/release-notes-6.0.0-rc1.md new file mode 100644 index 00000000000..86d0c2af597 --- /dev/null +++ b/doc/release-notes/release-notes-6.0.0-rc1.md @@ -0,0 +1,37 @@ +Notable changes +=============== + +- Windows builds have been fixed. + +Changelog +========= + +Daira-Emma Hopwood (2): + Ensure out-reference parameters of `CWallet::CreateTransaction` are initialized. + Rename ecc_addresses to bp_addresses in chainparams.cpp. + +Jack Grigg (16): + depends: Update Rust to 1.81.0 + depends: native_cmake 3.30.3 + depends: cxx 1.0.128 + cargo vet prune + cargo update + qa: Postpone Boost, LevelDB, and Clang updates + Fix clippy lints for 1.81 + Remove `#[should_panic]` tests of `extern "C"` functions + depends: Fix incompatibility between libsodium 1.0.20 and Clang 18 + depends: Downgrade libc++ for MinGW to 18.1.6-1 + Migrate to latest revision of Zcash Rust crates + depends: native_cmake 3.30.4 + Update release notes + Decrease support window to 6 weeks for 6.0.0-rc1 + make-release.py: Versioning changes for 6.0.0-rc1. + make-release.py: Updated manpages for 6.0.0-rc1. + +Kris Nuttycombe (1): + Use scopes to make it more obvious that certain variables are never used. + +y4ssi (2): + fix gitian-descriptors + Simplify Dockerfile (#6906) + diff --git a/doc/release-notes/release-notes-6.0.0.md b/doc/release-notes/release-notes-6.0.0.md new file mode 100644 index 00000000000..b53e8f1ce8b --- /dev/null +++ b/doc/release-notes/release-notes-6.0.0.md @@ -0,0 +1,84 @@ +Notable changes +=============== + +The mainnet activation of the NU6 network upgrade is supported by the 6.0.0 +release, with an activation height of 2726400, which should occur on +approximately November 23, 2024. Please upgrade to this release, or any +subsequent release, in order to follow the NU6 network upgrade. + +The following ZIPs are being deployed, or have been updated, as part of this upgrade: + +* [ZIP 207: Funding Streams (updated)](https://zips.z.cash/zip-0207) +* [ZIP 214: Consensus rules for a Zcash Development Fund (updated)](https://zips.z.cash/zip-0214) +* [ZIP 236: Blocks should balance exactly](https://zips.z.cash/zip-0236) +* [ZIP 253: Deployment of the NU6 Network Upgrade](https://zips.z.cash/zip-0253) +* [ZIP 1015: Block Reward Allocation for Non-Direct Development Funding](https://zips.z.cash/zip-1015) +* [ZIP 2001: Lockbox Funding Streams](https://zips.z.cash/zip-2001) + +In order to help the ecosystem prepare for the mainnet activation, NU6 has +already been activated on the Zcash testnet. Any node version 5.10.0 or higher, +including this release, supports the NU6 activation on testnet. + +Mining +------ + +- The default setting of `-blockunpaidactionlimit` is now zero, which has + the effect of no longer allowing "unpaid actions" in [block production]. + This adapts to current network conditions. If you have overridden this + setting as a miner, we recommend removing the override. This configuration + option may be removed entirely in a future release. + +[block production]: https://zips.z.cash/zip-0317#block-production + +Platform Support +---------------- + +- Windows builds have been fixed. + +Changelog +========= + +Daira-Emma Hopwood (9): + Ensure out-reference parameters of `CWallet::CreateTransaction` are initialized. + Rename ecc_addresses to bp_addresses in chainparams.cpp. + Make DEFAULT_BLOCK_UNPAID_ACTION_LIMIT zero. fixes #6899 (see that issue for rationale) + Add more detail to the "tx unpaid action limit exceeded" message. + Use at least the ZIP 317 fee for Sprout->Sapling migration. + Repair the RPC tests. + Add a regression test for the ZIP 317 default fee bug (#6956), and make the tests pass for now. + Code of Conduct: update email addresses and remove Sean as a contact. + Code of Conduct: add Kris and Str4d as contacts. + +Jack Grigg (24): + depends: Update Rust to 1.81.0 + depends: native_cmake 3.30.3 + depends: cxx 1.0.128 + cargo vet prune + cargo update + qa: Postpone Boost, LevelDB, and Clang updates + Fix clippy lints for 1.81 + Remove `#[should_panic]` tests of `extern "C"` functions + depends: Fix incompatibility between libsodium 1.0.20 and Clang 18 + depends: Downgrade libc++ for MinGW to 18.1.6-1 + Migrate to latest revision of Zcash Rust crates + depends: native_cmake 3.30.4 + Update release notes + Decrease support window to 6 weeks for 6.0.0-rc1 + make-release.py: Versioning changes for 6.0.0-rc1. + make-release.py: Updated manpages for 6.0.0-rc1. + make-release.py: Updated release notes and changelog for 6.0.0-rc1. + make-release.py: Updated book for 6.0.0-rc1. + qa: Add latest Clang release to postponed updates + Migrate to librustzcash crates revision right before NU6 mainnet height + Set support window back to the usual 16 weeks + Update release notes for 6.0.0 + make-release.py: Versioning changes for 6.0.0. + make-release.py: Updated manpages for 6.0.0. + +Kris Nuttycombe (1): + Use scopes to make it more obvious that certain variables are never used. + +y4ssi (2): + fix gitian-descriptors + Simplify Dockerfile (#6906) + diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index ebf18ad5c6a..5c3d68746e9 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -37,12 +37,11 @@ FLAKY_SCRIPTS = [ # These tests have intermittent failures that we haven't diagnosed yet. - 'mempool_nu_activation.py', + 'mempool_nu_activation.py', # this *may* be fixed 'mempool_packages.py', ] BASE_SCRIPTS= [ - # Scripts that are run by the travis build process # Longest test should go first, to favor running tests in parallel # vv Tests less than 5m vv 'wallet.py', @@ -94,6 +93,7 @@ 'wallet_sendmany_any_taddr.py', 'wallet_treestate.py', 'wallet_unified_change.py', + 'wallet_zip317_default.py', 'listtransactions.py', 'mempool_resurrect_test.py', 'txn_doublespend.py', diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 6d5251e63df..bb2eedfe044 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # @@ -32,6 +32,8 @@ OP_DROP, ) +from test_framework.zip317 import MARGINAL_FEE + from test_framework.mininode import ( COIN, CTransaction, @@ -50,7 +52,6 @@ def __init__(self): def setup_network(self): base_args = [ - '-minrelaytxfee=0', '-debug', '-txindex', '-experimentalfeatures', @@ -374,7 +375,7 @@ def check_balance(node_index, address, expected_balance, expected_received=None) tx.vout = [ CTxOut(1 * COIN, scriptPubKey), CTxOut(2 * COIN, scriptPubKey), - CTxOut(7 * COIN, scriptUnknown), + CTxOut(7 * COIN - 3 * MARGINAL_FEE, scriptUnknown), ] tx = self.nodes[0].signrawtransaction(hexlify(tx.serialize()).decode('utf-8')) txid = self.nodes[0].sendrawtransaction(tx['hex'], True) diff --git a/qa/rpc-tests/feature_zip239.py b/qa/rpc-tests/feature_zip239.py index b7b611990fd..12ae07fed91 100755 --- a/qa/rpc-tests/feature_zip239.py +++ b/qa/rpc-tests/feature_zip239.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Zcash developers +# Copyright (c) 2021-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -21,7 +21,6 @@ HEARTWOOD_BRANCH_ID, CANOPY_BRANCH_ID, NU5_BRANCH_ID, - LEGACY_DEFAULT_FEE, assert_equal, assert_false, assert_true, @@ -31,6 +30,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import ZIP_317_FEE from tx_expiry_helper import TestNode import os.path @@ -201,7 +201,7 @@ def run_test(self): opid = self.nodes[0].z_sendmany(sproutzaddr, [{ 'address': node1_taddr, 'amount': 1, - }], 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') + }], 1, ZIP_317_FEE, 'AllowRevealedRecipients') v4_txid = uint256_from_reversed_hex( wait_and_assert_operationid_status(self.nodes[0], opid) ) diff --git a/qa/rpc-tests/finalorchardroot.py b/qa/rpc-tests/finalorchardroot.py index d5a478b8dfc..9077b2294b6 100755 --- a/qa/rpc-tests/finalorchardroot.py +++ b/qa/rpc-tests/finalorchardroot.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -14,6 +14,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -33,7 +34,6 @@ def __init__(self): def setup_network(self, split=False): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-txindex', # Avoid JSONRPC error: No information available about transaction '-reindex', # Required due to enabling -txindex nuparams(NU5_BRANCH_ID, 200), @@ -138,9 +138,9 @@ def run_test(self): assert_equal(acct0, addrRes0['account']) assert_equal(addrRes0['receiver_types'], ['orchard']) orchardAddr0 = addrRes0['address'] - recipients = [] - recipients.append({"address": orchardAddr0, "amount": Decimal('10')}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": orchardAddr0, "amount": Decimal('10') - fee}] + myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -158,8 +158,8 @@ def run_test(self): assert_equal(len(result["orchard"]["actions"]), 2) assert_equal(blk["trees"]["orchard"]["size"], 2) - # Since there is a now orchard shielded input in the blockchain, - # the orchard values should have changed + # Since there is now an Orchard shielded input in the blockchain, + # the Orchard values should have changed new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["orchard"]["commitments"]["finalRoot"], root) assert_equal(new_treestate["sprout"], treestate["sprout"]) @@ -192,8 +192,9 @@ def run_test(self): # Mine a block with a Sprout shielded tx and verify the final Orchard root does not change zaddr0 = self.nodes[0].listaddresses()[0]['sprout']['addresses'][0] assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal('50')) + fee = conventional_fee(3) recipients = [{"address": taddr0, "amount": Decimal('12.34')}] - opid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, 0, 'AllowRevealedRecipients') + opid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], opid) self.sync_all() @@ -202,7 +203,7 @@ def run_test(self): blk = self.nodes[0].getblock("214") assert_equal(len(blk["tx"]), 2) - assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal("37.66")) + assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal("37.66") - fee) assert_equal(root, blk["finalorchardroot"]) assert_equal(blk["trees"]["orchard"]["size"], 2) @@ -218,7 +219,7 @@ def run_test(self): # Mine a block with a Sapling shielded tx and verify the final Orchard root does not change saplingAddr1 = self.nodes[1].z_getnewaddress("sapling") recipients = [{"address": saplingAddr1, "amount": Decimal('2.34')}] - myopid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, 0, 'AllowRevealedAmounts') + myopid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, ZIP_317_FEE, 'AllowRevealedAmounts') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -247,7 +248,7 @@ def run_test(self): assert_equal(addrRes1['receiver_types'], ['orchard']) orchardAddr1 = addrRes1['address'] recipients = [{"address": orchardAddr1, "amount": Decimal('2.34')}] - myopid = self.nodes[0].z_sendmany(orchardAddr0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(orchardAddr0, recipients, 1, ZIP_317_FEE) mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -275,9 +276,9 @@ def run_test(self): # Mine a block with an Orchard shielded sender and transparent recipient and verify the final Orchard root changes (because actions) taddr2 = self.nodes[0].getnewaddress() - recipients = [] - recipients.append({"address": taddr2, "amount": Decimal('2.34')}) - myopid = self.nodes[1].z_sendmany(orchardAddr1, recipients, 1, 0, 'AllowRevealedRecipients') + fee = conventional_fee(3) + recipients = [{"address": taddr2, "amount": Decimal('2.34') - fee}] + myopid = self.nodes[1].z_sendmany(orchardAddr1, recipients, 1, fee, 'AllowRevealedRecipients') mytxid = wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() @@ -286,7 +287,8 @@ def run_test(self): blk = self.nodes[0].getblock("217") assert_equal(len(blk["tx"]), 2) - assert_equal(self.nodes[0].z_getbalance(taddr2), Decimal("2.34")) + assert_equal(self.nodes[0].z_getbalance(taddr2), Decimal("2.34") - fee) + assert_equal(self.nodes[1].z_getbalance(orchardAddr1), 0) assert root != blk["finalorchardroot"] # Verify there is a Orchard output description (its commitment was added to tree) diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index ed4914ac749..7cee9a84c13 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -14,6 +14,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -33,7 +34,6 @@ def __init__(self): def setup_network(self, split=False): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-txindex', # Avoid JSONRPC error: No information available about transaction '-reindex', # Required due to enabling -txindex nuparams(NU5_BRANCH_ID, 210), @@ -105,9 +105,9 @@ def run_test(self): # Node 0 shields some funds taddr0 = get_coinbase_address(self.nodes[0]) saplingAddr0 = self.nodes[0].z_getnewaddress('sapling') - recipients = [] - recipients.append({"address": saplingAddr0, "amount": Decimal('10')}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": saplingAddr0, "amount": Decimal('10') - fee}] + myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -125,8 +125,8 @@ def run_test(self): assert_equal(len(result["vShieldedOutput"]), 2) # Non-coinbase bundles are padded assert_equal(blk["trees"]["sapling"]["size"], 2) - # Since there is a now sapling shielded input in the blockchain, - # the sapling values should have changed + # Since there is now a Sapling shielded input in the blockchain, + # the Sapling values should have changed new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root) assert_equal(new_treestate["sprout"], treestate["sprout"]) @@ -159,8 +159,9 @@ def run_test(self): # Mine a block with a Sprout shielded tx and verify the final Sapling root does not change zaddr0 = self.nodes[0].listaddresses()[0]['sprout']['addresses'][0] assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal('50')) + fee = conventional_fee(3) recipients = [{"address": taddr0, "amount": Decimal('12.34')}] - opid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, 0, 'AllowRevealedRecipients') + opid = self.nodes[0].z_sendmany(zaddr0, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], opid) self.sync_all() @@ -169,7 +170,7 @@ def run_test(self): blk = self.nodes[0].getblock("204") assert_equal(len(blk["tx"]), 2) - assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal("37.66")) + assert_equal(self.nodes[0].z_getbalance(zaddr0), Decimal("37.66") - fee) assert_equal(root, blk["finalsaplingroot"]) assert_equal(blk["trees"]["sapling"]["size"], 2) @@ -185,7 +186,7 @@ def run_test(self): # Mine a block with a Sapling shielded recipient and verify the final Sapling root changes saplingAddr1 = self.nodes[1].z_getnewaddress("sapling") recipients = [{"address": saplingAddr1, "amount": Decimal('2.34')}] - myopid = self.nodes[0].z_sendmany(saplingAddr0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(saplingAddr0, recipients, 1, ZIP_317_FEE) mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -212,9 +213,9 @@ def run_test(self): # Mine a block with a Sapling shielded sender and transparent recipient. taddr2 = self.nodes[0].getnewaddress() - recipients = [] - recipients.append({"address": taddr2, "amount": Decimal('2.34')}) - myopid = self.nodes[1].z_sendmany(saplingAddr1, recipients, 1, 0, 'AllowRevealedRecipients') + fee = conventional_fee(3) + recipients = [{"address": taddr2, "amount": Decimal('2.34') - fee}] + myopid = self.nodes[1].z_sendmany(saplingAddr1, recipients, 1, fee, 'AllowRevealedRecipients') mytxid = wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() @@ -224,13 +225,11 @@ def run_test(self): blk = self.nodes[0].getblock("206") assert_equal(len(blk["tx"]), 2) assert_equal(mytxid, blk["tx"][1]) - assert_equal(self.nodes[0].z_getbalance(taddr2), Decimal("2.34")) + assert_equal(self.nodes[0].z_getbalance(taddr2), Decimal("2.34") - fee) assert_equal(self.nodes[1].z_getbalance(saplingAddr1), 0) # Verify the final Sapling root changes (because the Sapling bundle was padded # with 2 dummy outputs). - print(self.nodes[0].getrawtransaction(blk["tx"][0])) - print(self.nodes[0].getrawtransaction(blk["tx"][1])) root = blk["finalsaplingroot"] assert root != self.nodes[0].getblock("205")["finalsaplingroot"] assert_equal(blk["trees"]["sapling"]["size"], 6) diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 7b7c3ec6fa0..0d97b7a9021 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,7 +9,6 @@ from test_framework.util import ( assert_equal, CANOPY_BRANCH_ID, - LEGACY_DEFAULT_FEE, NU5_BRANCH_ID, get_coinbase_address, hex_str_to_bytes, @@ -24,6 +23,8 @@ from test_framework.blocktools import ( create_block ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE + from decimal import Decimal class GetBlockTemplateTest(BitcoinTestFramework): @@ -52,13 +53,14 @@ 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, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') + myopid = node.z_sendmany(self.sprout_addr, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') wait_and_assert_operationid_status(node, myopid) def add_nu5_v5_tx_to_mempool(self): node = self.node - recipients = [{"address": self.unified_addr, "amount": Decimal('9.99999')}] - myopid = node.z_sendmany(get_coinbase_address(node), recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": self.unified_addr, "amount": Decimal('10') - fee}] + myopid = node.z_sendmany(get_coinbase_address(node), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(node, myopid) def add_transparent_tx_to_mempool(self): @@ -196,7 +198,6 @@ def run_test(self): print("- block with 6 Orchard transactions (plus coinbase)") for i in range(0, 6): - print(str(node.z_getbalance(self.transparent_addr))) self.add_nu5_v5_tx_to_mempool() self.gbt_submitblock(True) diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py index 369bc4d9c29..1b2d4cf6322 100755 --- a/qa/rpc-tests/invalidtxrequest.py +++ b/qa/rpc-tests/invalidtxrequest.py @@ -1,15 +1,17 @@ #!/usr/bin/env python3 -# +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2021-2024 The Zcash developers # Distributed under the MIT/X11 software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # from test_framework.test_framework import ComparisonTestFramework from test_framework.comptool import TestManager, TestInstance, RejectResult -from test_framework.mininode import NetworkThread +from test_framework.mininode import NetworkThread, COIN from test_framework.blocktools import create_block, create_coinbase, create_transaction -import time +from test_framework.zip317 import MINIMUM_FEE +import time ''' In this test we connect to one node over p2p, and test tx requests. @@ -19,7 +21,6 @@ class InvalidTxRequestTest(ComparisonTestFramework): def __init__(self): super().__init__() - self.additional_args = ['-minrelaytxfee=0'] ''' 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. ''' @@ -64,7 +65,7 @@ def get_tests(self): # b'\x64' is OP_NOTIF # Transaction will be rejected with code 16 (REJECT_INVALID) - tx1 = create_transaction(self.block1.vtx[0], 0, b'\x64', 10*100000000) + tx1 = create_transaction(self.block1.vtx[0], 0, b'\x64', 10*COIN - MINIMUM_FEE) yield TestInstance([[tx1, RejectResult(16, b'mandatory-script-verify-flag-failed')]]) # TODO: test further transactions... diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 874f238b5e0..00b6e9340c2 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2019-2022 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -67,28 +67,24 @@ def run_test(self): zaddr1 = self.nodes[0].z_getnewaddress('sapling') zaddr2 = self.nodes[0].z_getnewaddress('sapling') zaddr3 = self.nodes[0].z_getnewaddress('sapling') - fee = conventional_fee(2) print("Filling mempool...") - opid1 = self.nodes[1].z_sendmany( - get_coinbase_address(self.nodes[1]), - [{"address": zaddr1, "amount": Decimal('10.0') - fee}], - 1, fee, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": zaddr1, "amount": Decimal('10.0') - fee}] + opid1 = self.nodes[1].z_sendmany(get_coinbase_address(self.nodes[1]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[1], opid1) - opid2 = self.nodes[2].z_sendmany( - get_coinbase_address(self.nodes[2]), - [{"address": zaddr2, "amount": Decimal('10.0') - fee}], - 1, fee, 'AllowRevealedSenders') + + recipients = [{"address": zaddr2, "amount": Decimal('10.0') - fee}] + opid2 = self.nodes[2].z_sendmany(get_coinbase_address(self.nodes[2]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[2], opid2) + self.sync_all() self.check_mempool_sizes(2) print("Adding one more transaction...") - opid3 = self.nodes[3].z_sendmany( - get_coinbase_address(self.nodes[3]), - [{"address": zaddr3, "amount": Decimal('10.0') - fee}], - 1, fee, 'AllowRevealedSenders') + recipients = [{"address": zaddr3, "amount": Decimal('10.0') - fee}] + opid3 = self.nodes[3].z_sendmany(get_coinbase_address(self.nodes[3]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[3], opid3) # The mempools are no longer guaranteed to be in a consistent state, so we cannot sync sleep(5) @@ -106,9 +102,10 @@ def run_test(self): print("Checking mempool size reset after block mined...") self.check_mempool_sizes(0) zaddr4 = self.nodes[0].z_getnewaddress('sapling') - opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('10.0') - 2*fee}], 1) + recipients = [{"address": zaddr4, "amount": Decimal('10.0') - 2*fee}] + opid4 = self.nodes[0].z_sendmany(zaddr1, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], opid4) - opid5 = self.nodes[0].z_sendmany(zaddr2, [{"address": zaddr4, "amount": Decimal('10.0') - 2*fee}], 1) + opid5 = self.nodes[0].z_sendmany(zaddr2, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], opid5) self.sync_all() diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index 43c8691a3f5..76ae41754f3 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -1,20 +1,21 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 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.mininode import NU5_PROTO_VERSION from test_framework.util import ( BLOSSOM_BRANCH_ID, CANOPY_BRANCH_ID, HEARTWOOD_BRANCH_ID, NU5_BRANCH_ID, + NU6_BRANCH_ID, assert_equal, assert_true, nuparams, start_node, connect_nodes, wait_and_assert_operationid_status, get_coinbase_address ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -30,18 +31,17 @@ def __init__(self): def setup_network(self): args = [ - '-minrelaytxfee=0', '-checkmempool', '-debug=mempool', '-blockmaxsize=4000', '-allowdeprecated=getnewaddress', - '-allowdeprecated=legacy_privacy', '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', nuparams(BLOSSOM_BRANCH_ID, 200), nuparams(HEARTWOOD_BRANCH_ID, 210), nuparams(CANOPY_BRANCH_ID, 220), nuparams(NU5_BRANCH_ID, 230), + nuparams(NU6_BRANCH_ID, 240), ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) @@ -62,9 +62,13 @@ def run_test(self): # Shield some ZEC node1_taddr = get_coinbase_address(self.nodes[1]) node0_zaddr = self.nodes[0].z_getnewaddress('sapling') - recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] - myopid = self.nodes[1].z_sendmany(node1_taddr, recipients, 1, 0) - print(wait_and_assert_operationid_status(self.nodes[1], myopid)) + coinbase_fee = conventional_fee(3) + recipients = [{'address': node0_zaddr, 'amount': Decimal('10') - coinbase_fee}] + myopid = self.nodes[1].z_sendmany(node1_taddr, recipients, 1, coinbase_fee, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[1], myopid) + node0_balance = Decimal('10') - coinbase_fee + fee = conventional_fee(2) + self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -79,14 +83,22 @@ def nu_activation_checks(): assert_equal(set(self.nodes[0].getrawmempool()), set()) # Check node 0 shielded balance - assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(node0_zaddr), node0_balance) # Fill the mempool with more transactions than can fit into 4 blocks + # (note `-blockmaxsize=4000` in the node arguments). node0_taddr = self.nodes[0].getnewaddress() x_txids = [] + print("Filling mempool", end="", flush=True) while self.nodes[1].getmempoolinfo()['bytes'] < 8 * 4000: x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) + if len(x_txids) % 10 == 0: + print(".", end="", flush=True) + # this sync is important for reliability + self.sync_all() + self.sync_all() + print(" done") # Spends should be in the mempool x_mempool = set(self.nodes[0].getrawmempool()) @@ -147,8 +159,8 @@ def nu_activation_checks(): self.sync_all() # Create a shielded Y transaction - recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] - myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients, 1,0) + recipients = [{'address': node0_zaddr, 'amount': node0_balance - fee}] + myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients, 1, fee) shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) assert(shielded != None) y_txids.append(shielded) @@ -179,7 +191,7 @@ def nu_activation_checks(): assert_equal(set(self.nodes[1].getrawmempool()), set(y_txids)) # Node 0 note should be spendable again - assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(node0_zaddr), node0_balance) # Reconsider block H - 1. self.nodes[0].reconsiderblock(block_hm1) @@ -189,28 +201,31 @@ def nu_activation_checks(): self.nodes[1].generate(6) self.sync_all() - net_version = self.nodes[0].getnetworkinfo()["protocolversion"] - print('Testing Sapling -> Blossom activation boundary') - # Current height = 195 + assert_equal(self.nodes[0].getblockcount(), 195) nu_activation_checks() - # Current height = 205 + node0_balance -= fee + assert_equal(self.nodes[0].getblockcount(), 205) print('Testing Blossom -> Heartwood activation boundary') nu_activation_checks() - # Current height = 215 + node0_balance -= fee + assert_equal(self.nodes[0].getblockcount(), 215) print('Testing Heartwood -> Canopy activation boundary') nu_activation_checks() - # Current height = 225 - - if net_version < NU5_PROTO_VERSION: - print("Node's block index is not NU5-aware, skipping remaining tests") - return + node0_balance -= fee + assert_equal(self.nodes[0].getblockcount(), 225) print('Testing Canopy -> NU5 activation boundary') nu_activation_checks() - # Current height = 235 + node0_balance -= fee + assert_equal(self.nodes[0].getblockcount(), 235) + + print('Testing NU5 -> NU6 activation boundary') + nu_activation_checks() + node0_balance -= fee + assert_equal(self.nodes[0].getblockcount(), 245) if __name__ == '__main__': MempoolUpgradeActivationTest().main() diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 73d224ca589..7b3882df3c0 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,7 +29,6 @@ class MempoolPackagesTest(BitcoinTestFramework): def setup_network(self): base_args = [ '-limitdescendantcount=%d' % (self.limitdescendantcount,), - '-minrelaytxfee=0', '-maxorphantx=%d' % (self.limitdescendantcount,), '-debug', '-allowdeprecated=getnewaddress', @@ -63,7 +63,7 @@ def run_test(self): vout = utxo[0]['vout'] value = utxo[0]['amount'] - fee = conventional_fee(2) + fee = conventional_fee(10) # 100 transactions off a confirmed tx should be fine chain = [] for i in range(100): diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index 06e9d1f5b54..8d9f01374cf 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2019-2022 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,9 +9,12 @@ # that spend (directly or indirectly) coinbase transactions. # +from decimal import Decimal + from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, assert_raises, start_node, connect_nodes +from test_framework.zip317 import conventional_fee # Create one-input, one-output, no-fee transaction: @@ -24,7 +27,6 @@ def __init__(self): def setup_network(self): args = [ - '-minrelaytxfee=0', '-checkmempool', '-debug=mempool', '-allowdeprecated=getnewaddress', @@ -61,12 +63,13 @@ def run_test(self): # and make sure the mempool code behaves correctly. b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ] coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] - spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, 10) - spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, 10) - spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, 10) + fee = conventional_fee(2) + spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, Decimal('10') - fee) + spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, Decimal('10') - fee) + spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, Decimal('10') - fee) # Create a block-height-locked transaction which will be invalid after reorg - timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 10}) + timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: Decimal('10') - fee}) # Set the time lock, ensuring we don't clobber the rest of the Sapling v4 tx format timelock_tx = timelock_tx.replace("ffffffff", "11111111", 1) timelock_tx = timelock_tx[:-38] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" + timelock_tx[-30:] @@ -80,8 +83,8 @@ def run_test(self): assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) # Create 102_1 and 103_1: - spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 10) - spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 10) + spend_102_1_raw = self.create_tx(spend_102_id, node1_address, Decimal('10') - 2*fee) + spend_103_1_raw = self.create_tx(spend_103_id, node1_address, Decimal('10') - 2*fee) # Broadcast and mine 103_1: spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py index 1d317501818..1b0264a0f2f 100755 --- a/qa/rpc-tests/mempool_resurrect_test.py +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -10,7 +10,8 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_node, LEGACY_DEFAULT_FEE +from test_framework.util import assert_equal, start_node +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -25,7 +26,6 @@ def __init__(self): def setup_network(self): # Just need one node for this test args = [ - '-minrelaytxfee=0', '-checkmempool', '-debug=mempool', '-allowdeprecated=getnewaddress', @@ -56,13 +56,14 @@ def run_test(self): b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ] coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] - spends1_raw = [ self.create_tx(txid, node0_address, 10) for txid in coinbase_txids ] + fee = conventional_fee(1) + spends1_raw = [ self.create_tx(txid, node0_address, Decimal('10') - fee) for txid in coinbase_txids ] spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ] blocks = [] blocks.extend(self.nodes[0].generate(1)) - spends2_raw = [ self.create_tx(txid, node0_address, Decimal('10.0') - LEGACY_DEFAULT_FEE) for txid in spends1_id ] + spends2_raw = [ self.create_tx(txid, node0_address, Decimal('10') - 2*fee) for txid in spends1_id ] spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ] blocks.extend(self.nodes[0].generate(1)) diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 43da9f90590..809bdf47780 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -14,10 +14,13 @@ # but less mature coinbase spends are NOT. # +from decimal import Decimal + from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, assert_greater_than, assert_raises, \ start_node +from test_framework.zip317 import conventional_fee # Create one-input, one-output, no-fee transaction: @@ -30,7 +33,6 @@ def __init__(self): def setup_network(self): # Just need one node for this test args = [ - '-minrelaytxfee=0', '-checkmempool', '-debug=mempool', '-allowdeprecated=getnewaddress', @@ -57,7 +59,8 @@ def run_test(self): # is too immature to spend. b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ] coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] - spends_raw = [ self.create_tx(txid, node0_address, 10) for txid in coinbase_txids ] + fee = conventional_fee(1) + spends_raw = [ self.create_tx(txid, node0_address, Decimal('10') - fee) for txid in coinbase_txids ] spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) diff --git a/qa/rpc-tests/mempool_tx_expiry.py b/qa/rpc-tests/mempool_tx_expiry.py index 9359ded5193..3bec6abd92e 100755 --- a/qa/rpc-tests/mempool_tx_expiry.py +++ b/qa/rpc-tests/mempool_tx_expiry.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -11,7 +11,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, \ connect_nodes_bi, sync_blocks, start_nodes, \ - wait_and_assert_operationid_status, LEGACY_DEFAULT_FEE + wait_and_assert_operationid_status from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -23,7 +23,6 @@ class MempoolTxExpiryTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-txexpirydelta=%d' % TX_EXPIRY_DELTA, '-debug=mempool', '-allowdeprecated=getnewaddress', @@ -43,7 +42,7 @@ def run_test(self): self.split_network() # Test dependent txs - firstTx = self.nodes[0].sendtoaddress(alice, 0.1) + firstTx = self.nodes[0].sendtoaddress(alice, Decimal('0.1')) firstTxInfo = self.nodes[0].getrawtransaction(firstTx, 1) assert_equal(firstTxInfo["version"], 4) assert_equal(firstTxInfo["overwintered"], True) @@ -56,7 +55,8 @@ def run_test(self): vout = outpoint break inputs = [{'txid': firstTx, 'vout': vout['n'], 'scriptPubKey': vout['scriptPubKey']['hex']}] - outputs = {alice: 0.1} + fee = conventional_fee(2) + outputs = {alice: Decimal('0.1') - fee} rawTx = self.nodes[0].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[0].signrawtransaction(rawTx) assert(rawTxSigned['complete']) @@ -79,7 +79,8 @@ def run_test(self): assert_equal(set(self.nodes[2].getrawmempool()), set()) ## Shield one of Alice's coinbase funds to her zaddr - res = self.nodes[0].z_shieldcoinbase("*", z_alice, LEGACY_DEFAULT_FEE, 1) + coinbase_fee = conventional_fee(3) + res = self.nodes[0].z_shieldcoinbase("*", z_alice, coinbase_fee, 1) wait_and_assert_operationid_status(self.nodes[0], res['opid']) self.nodes[0].generate(1) self.sync_all() @@ -87,17 +88,16 @@ def run_test(self): # Get balance on node 0 bal = self.nodes[0].z_gettotalbalance() print("Balance before zsend, after shielding 10: ", bal) - assert_equal(Decimal(bal["private"]), Decimal('10.0') - LEGACY_DEFAULT_FEE) + assert_equal(Decimal(bal["private"]), Decimal('10.0') - coinbase_fee) print("Splitting network...") self.split_network() # Create transactions blockheight = self.nodes[0].getblockchaininfo()['blocks'] - zsendamount = Decimal('1.0') - conventional_fee(2) - recipients = [] - recipients.append({"address": z_bob, "amount": zsendamount}) - myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1) + fee = conventional_fee(2) + recipients = [{"address": z_bob, "amount": Decimal('1.0') - fee}] + myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1, fee) persist_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) persist_transparent = self.nodes[0].sendtoaddress(bob, 0.01) # Verify transparent transaction is version 4 intended for Sapling branch @@ -196,9 +196,10 @@ def run_test(self): print("\nBlockheight advances to greater than expiry block height. After reorg, txs should expire from mempool") print("Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance()) - myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1) + fee = conventional_fee(2) + myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1, fee) expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) - expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01) + expire_transparent = self.nodes[0].sendtoaddress(bob, Decimal('0.01')) print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks']) print("Blockheight node 2 at expire_shielded creation:", self.nodes[2].getblockchaininfo()['blocks']) print("Expiryheight of expire_transparent:", self.nodes[0].getrawtransaction(expire_transparent, 1)['expiryheight']) @@ -220,7 +221,7 @@ def run_test(self): print("Ensure balance of node 0 is correct") bal = self.nodes[0].z_gettotalbalance() print("Balance after expire_shielded has expired: ", bal) - assert_equal(Decimal(bal["private"]), Decimal('8.0') - LEGACY_DEFAULT_FEE) + assert_equal(Decimal(bal["private"]), Decimal('8.0') - coinbase_fee) print("Splitting network...") self.split_network() @@ -229,7 +230,7 @@ def run_test(self): print("Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance()) myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1) expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) - expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01) + expire_transparent = self.nodes[0].sendtoaddress(bob, Decimal('0.01')) print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks']) print("Blockheight node 2 at expire_shielded creation:", self.nodes[2].getblockchaininfo()['blocks']) print("Expiryheight of expire_transparent:", self.nodes[0].getrawtransaction(expire_transparent, 1)['expiryheight']) diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index 19d28b14c75..8c23093789b 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -10,8 +10,8 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, connect_nodes_bi, fail, \ initialize_chain_clean, start_node, \ - wait_and_assert_operationid_status, LEGACY_DEFAULT_FEE -from test_framework.zip317 import conventional_fee + wait_and_assert_operationid_status +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -39,7 +39,6 @@ def setup_chain(self, test): def setup_network(self, test, additional_args=[]): args = [ - '-minrelaytxfee=0', '-debug=zrpcunsafe', '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', @@ -86,26 +85,36 @@ def generate_and_check(node, expected_transactions): # Shield the coinbase myzaddr = self.new_address(test, 0) - result = test.nodes[0].z_shieldcoinbase("*", myzaddr, 0, None, None, 'AllowLinkingAccountAddresses') + fee = conventional_fee(7) + result = test.nodes[0].z_shieldcoinbase("*", myzaddr, fee, None, None, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(test.nodes[0], result['opid']) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_myzaddr = Decimal('50') - fee + + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) # Prepare some UTXOs and notes for merging mytaddr = test.nodes[0].getnewaddress() mytaddr2 = test.nodes[0].getnewaddress() mytaddr3 = test.nodes[0].getnewaddress() + fee = conventional_fee(6) result = test.nodes[0].z_sendmany(myzaddr, [ {'address': do_not_shield_taddr, 'amount': Decimal('10')}, {'address': mytaddr, 'amount': Decimal('10')}, {'address': mytaddr2, 'amount': Decimal('10')}, {'address': mytaddr3, 'amount': Decimal('10')}, - ], 1, 0, 'AllowRevealedRecipients') + ], 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(test.nodes[0], result) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_myzaddr -= Decimal('40') + fee + expected_mytaddr = Decimal('10') + + assert_equal(test.nodes[0].z_getbalance(mytaddr), expected_mytaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) # Merging will fail because from arguments need to be in an array assert_mergetoaddress_exception( @@ -136,22 +145,22 @@ def generate_and_check(node, expected_transactions): # Merging will fail because transparent limit parameter must be at least 0 assert_mergetoaddress_exception( "Limit on maximum number of UTXOs cannot be negative", - lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, Decimal('0.001'), -1)) + lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, -1)) # Merging will fail because transparent limit parameter is absurdly large assert_mergetoaddress_exception( "JSON integer out of range", - lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, Decimal('0.001'), 99999999999999)) + lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, 99999999999999)) # Merging will fail because shielded limit parameter must be at least 0 assert_mergetoaddress_exception( "Limit on maximum number of notes cannot be negative", - lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, Decimal('0.001'), 50, -1)) + lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, 50, -1)) # Merging will fail because shielded limit parameter is absurdly large assert_mergetoaddress_exception( "JSON integer out of range", - lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, Decimal('0.001'), 50, 99999999999999)) + lambda: test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, 50, 99999999999999)) # Merging will fail for this specific case where it would spend a fee and do nothing assert_mergetoaddress_exception( @@ -164,22 +173,27 @@ def generate_and_check(node, expected_transactions): lambda: test.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], mytaddr)) # Merge UTXOs from node 0 of value 30, default fee - result = test.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr, None, None, None, None, 'AllowLinkingAccountAddresses') + fee = conventional_fee(5) + result = test.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr, fee, None, None, None, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(test.nodes[0], result['opid']) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_myzaddr += Decimal('30') - fee + expected_mytaddr = 0 # Confirm balances and that do_not_shield_taddr containing funds of 10 was left alone assert_equal(test.nodes[0].getbalance(), Decimal('10')) assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10')) - assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('40') - conventional_fee(5)) + assert_equal(test.nodes[0].z_getbalance(mytaddr), expected_mytaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) assert_equal(test.nodes[1].getbalance(), Decimal('40')) assert_equal(test.nodes[2].getbalance(), Decimal('30')) # Shield all notes to another z-addr myzaddr2 = self.new_address(test, 0) - result = test.nodes[0].z_mergetoaddress(self.any_zaddr, myzaddr2, 0) + fee = conventional_fee(2) + result = test.nodes[0].z_mergetoaddress(self.any_zaddr, myzaddr2, fee) assert_equal(result["mergingUTXOs"], 0) assert_equal(result["remainingUTXOs"], 0) assert_equal(result["mergingNotes"], 2) @@ -188,54 +202,65 @@ def generate_and_check(node, expected_transactions): test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_myzaddr2 = expected_myzaddr - fee + expected_myzaddr = 0 - assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('0')) - assert_equal(test.nodes[0].z_getbalance(myzaddr2), Decimal('40') - conventional_fee(5)) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr2), expected_myzaddr2) - # Shield coinbase UTXOs from any node 2 taddr, and set fee to 0 - result = test.nodes[2].z_shieldcoinbase("*", myzaddr, 0, None, None, 'AllowLinkingAccountAddresses') + # Shield coinbase UTXOs from any node 2 taddr + fee = conventional_fee(5) + result = test.nodes[2].z_shieldcoinbase("*", myzaddr, fee, None, None, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(test.nodes[2], result['opid']) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_myzaddr += Decimal('30') - fee assert_equal(test.nodes[0].getbalance(), Decimal('10')) - assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('30')) - assert_equal(test.nodes[0].z_getbalance(myzaddr2), Decimal('40') - conventional_fee(5)) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr2), expected_myzaddr2) assert_equal(test.nodes[1].getbalance(), Decimal('60')) assert_equal(test.nodes[2].getbalance(), Decimal('0')) - # Merge all notes from node 0 into a node 0 taddr, and set fee to 0 - result = test.nodes[0].z_mergetoaddress(self.any_zaddr, mytaddr, 0, None, None, None, 'AllowRevealedRecipients') + # Merge all notes from node 0 into a node 0 taddr + fee = conventional_fee(3) + result = test.nodes[0].z_mergetoaddress(self.any_zaddr, mytaddr, fee, None, None, None, 'AllowRevealedRecipients') wait_and_assert_operationid_status(test.nodes[0], result['opid']) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() + expected_mytaddr += expected_myzaddr + expected_myzaddr2 - fee + expected_myzaddr = 0 + expected_myzaddr2 = 0 - assert_equal(test.nodes[0].getbalance(), Decimal('80') - conventional_fee(5)) + assert_equal(test.nodes[0].getbalance(), Decimal('10') + expected_mytaddr) assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10')) - assert_equal(test.nodes[0].z_getbalance(mytaddr), Decimal('70') - conventional_fee(5)) - assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('0')) - assert_equal(test.nodes[0].z_getbalance(myzaddr2), Decimal('0')) + assert_equal(test.nodes[0].z_getbalance(mytaddr), expected_mytaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr2), expected_myzaddr2) assert_equal(test.nodes[1].getbalance(), Decimal('70')) assert_equal(test.nodes[2].getbalance(), Decimal('0')) - # Merge all node 0 UTXOs together into a node 1 taddr, and set fee to 0 + # Merge all node 0 UTXOs together into a node 1 taddr test.nodes[1].getnewaddress() # Ensure we have an empty address n1taddr = test.nodes[1].getnewaddress() - result = test.nodes[0].z_mergetoaddress(["ANY_TADDR"], n1taddr, 0, None, None, None, 'NoPrivacy') + fee = conventional_fee(4) + result = test.nodes[0].z_mergetoaddress(["ANY_TADDR"], n1taddr, fee, None, None, None, 'NoPrivacy') wait_and_assert_operationid_status(test.nodes[0], result['opid']) test.sync_all() generate_and_check(test.nodes[1], 2) test.sync_all() assert_equal(0, len(test.nodes[0].z_listunspent(0))) + expected_n1taddr = Decimal('10') + expected_mytaddr - fee + expected_mytaddr = 0 assert_equal(test.nodes[0].getbalance(), Decimal('0')) assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('0')) - assert_equal(test.nodes[0].z_getbalance(mytaddr), Decimal('0')) - assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('0')) - assert_equal(test.nodes[1].getbalance(), Decimal('160') - conventional_fee(5)) - assert_equal(test.nodes[1].z_getbalance(n1taddr), Decimal('80') - conventional_fee(5)) + assert_equal(test.nodes[0].z_getbalance(mytaddr), expected_mytaddr) + assert_equal(test.nodes[0].z_getbalance(myzaddr), expected_myzaddr) + assert_equal(test.nodes[1].getbalance(), Decimal('80') + expected_n1taddr) + assert_equal(test.nodes[1].z_getbalance(n1taddr), expected_n1taddr) assert_equal(test.nodes[2].getbalance(), Decimal('0')) # Generate 5 regular UTXOs on node 0, and 20 regular UTXOs on node 2. @@ -251,7 +276,7 @@ def generate_and_check(node, expected_transactions): test.sync_all() # This z_mergetoaddress and the one below result in two notes in myzaddr. - result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, LEGACY_DEFAULT_FEE, None, None, None, 'AllowRevealedSenders') + result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, ZIP_317_FEE, None, None, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 5) assert_equal(result["remainingUTXOs"], 0) assert_equal(result["mergingNotes"], 0) @@ -259,7 +284,7 @@ def generate_and_check(node, expected_transactions): wait_and_assert_operationid_status(test.nodes[0], result['opid']) # Verify maximum number of UTXOs is not limited when the limit parameter is set to 0. - result = test.nodes[2].z_mergetoaddress([n2taddr], myzaddr, LEGACY_DEFAULT_FEE, 0, None, None, 'AllowRevealedSenders') + result = test.nodes[2].z_mergetoaddress([n2taddr], myzaddr, ZIP_317_FEE, 0, None, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 20) assert_equal(result["remainingUTXOs"], 0) assert_equal(result["mergingNotes"], 0) @@ -276,7 +301,7 @@ def generate_and_check(node, expected_transactions): test.nodes[1].sendtoaddress(mytaddr, 1) generate_and_check(test.nodes[1], 101) test.sync_all() - result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, conventional_fee(52), None, None, None, 'AllowRevealedSenders') + result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, ZIP_317_FEE, None, None, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 50) assert_equal(result["remainingUTXOs"], 50) assert_equal(result["mergingNotes"], 0) @@ -288,7 +313,7 @@ def generate_and_check(node, expected_transactions): assert_equal(3, len(test.nodes[0].z_listunspent(0))) # Verify maximum number of UTXOs which node 0 can shield can be set by the limit parameter - result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, conventional_fee(35), 33, None, None, 'AllowRevealedSenders') + result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, ZIP_317_FEE, 33, None, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 33) assert_equal(result["remainingUTXOs"], 17) assert_equal(result["mergingNotes"], 0) @@ -303,7 +328,7 @@ def generate_and_check(node, expected_transactions): # NB: We can’t yet merge from UAs, so ensure we’re not before running these cases if (myzaddr[0] != 'u'): # Also check that we can set off a second merge before the first one is complete - result1 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, LEGACY_DEFAULT_FEE, 50, 2) + result1 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, ZIP_317_FEE, 50, 2) # First merge should select from all notes assert_equal(result1["mergingUTXOs"], 0) @@ -313,7 +338,7 @@ def generate_and_check(node, expected_transactions): assert_equal(result1["remainingNotes"], 2) # Second merge should ignore locked notes - result2 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, LEGACY_DEFAULT_FEE, 50, 2) + result2 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, ZIP_317_FEE, 50, 2) assert_equal(result2["mergingUTXOs"], 0) assert_equal(result2["remainingUTXOs"], 0) assert_equal(result2["mergingNotes"], 2) @@ -326,7 +351,7 @@ def generate_and_check(node, expected_transactions): test.sync_all() # Shield both UTXOs and notes to a z-addr - result = test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, LEGACY_DEFAULT_FEE, 10, 2, None, 'AllowRevealedSenders') + result = test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, 10, 2, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 10) assert_equal(result["remainingUTXOs"], 7) assert_equal(result["mergingNotes"], 2) @@ -334,7 +359,7 @@ def generate_and_check(node, expected_transactions): wait_and_assert_operationid_status(test.nodes[0], result['opid']) else: # Shield both UTXOs and notes to a z-addr - result = test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, LEGACY_DEFAULT_FEE, 10, 2, None, 'AllowRevealedSenders') + result = test.nodes[0].z_mergetoaddress(self.any_zaddr_or_utxo, myzaddr, ZIP_317_FEE, 10, 2, None, 'AllowRevealedSenders') assert_equal(result["mergingUTXOs"], 10) assert_equal(result["remainingUTXOs"], 7) assert_equal(result["mergingNotes"], 2) diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py index 968d5b5fb1f..524a85dc686 100755 --- a/qa/rpc-tests/mergetoaddress_mixednotes.py +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -7,6 +7,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, get_coinbase_address, \ start_nodes, wait_and_assert_operationid_status +from test_framework.zip317 import conventional_fee from mergetoaddress_helper import assert_mergetoaddress_exception @@ -18,7 +19,6 @@ def __init__(self): def setup_nodes(self): self.num_nodes = 4 return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-anchorconfirmations=1', '-allowdeprecated=getnewaddress', '-allowdeprecated=legacy_privacy', @@ -38,10 +38,11 @@ def run_test(self): assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('200')) # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sprout Notes + fee = conventional_fee(3) assert_mergetoaddress_exception( "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) - opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": saplingAddr, "amount": Decimal('10')}], 1, 0, 'AllowRevealedSenders') + opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": saplingAddr, "amount": Decimal('10') - fee}], 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], opid) self.nodes[0].generate(1) self.sync_all() @@ -49,28 +50,28 @@ def run_test(self): assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('200')) # Merge Sprout -> taddr - result = self.nodes[0].z_mergetoaddress(["ANY_SPROUT"], t_addr, 0) + result = self.nodes[0].z_mergetoaddress(["ANY_SPROUT"], t_addr) 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('0')) - assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('10')) - assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('250')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('10') - fee) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('250') - fee) # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sapling Notes assert_mergetoaddress_exception( "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", - lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) + lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr, fee)) # Merge Sapling -> taddr - result = self.nodes[0].z_mergetoaddress(["ANY_SAPLING"], t_addr, 0) + result = self.nodes[0].z_mergetoaddress(["ANY_SAPLING"], t_addr, fee) 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('0')) assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) - assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('260')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('260') - 3*fee) if __name__ == '__main__': diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index 9778b7d589d..c8f66e1b79d 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -11,8 +11,8 @@ import string from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, assert_raises, \ - start_node, connect_nodes +from test_framework.util import assert_equal, assert_raises_message, start_node, connect_nodes +from test_framework.zip317 import conventional_fee class MerkleBlockTest(BitcoinTestFramework): @@ -24,7 +24,6 @@ def __init__(self): def setup_network(self): base_args = [ - '-minrelaytxfee=0', '-debug', '-allowdeprecated=getnewaddress', ] @@ -53,11 +52,11 @@ def run_test(self): assert_equal(self.nodes[2].getbalance(), 0) node0utxos = self.nodes[0].listunspent(1) - tx1 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 10}) + tx1 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 10 - conventional_fee(1)}) txid1 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx1)["hex"]) - tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 10}) + tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 10 - conventional_fee(1)}) txid2 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx2)["hex"]) - assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [txid1]) + assert_raises_message(JSONRPCException, "Transaction not yet in block", self.nodes[0].gettxoutproof, [txid1]) self.nodes[0].generate(1) blockhash = self.nodes[0].getblockhash(chain_height + 1) @@ -73,7 +72,7 @@ def run_test(self): assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2], blockhash)), txlist) txin_spent = self.nodes[1].listunspent(1).pop() - tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 10}) + tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 10 - 2*conventional_fee(1)}) self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"]) self.nodes[0].generate(1) self.sync_all() @@ -82,7 +81,7 @@ def run_test(self): txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 # We can't find the block from a fully-spent tx - assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent]) + assert_raises_message(JSONRPCException, "Transaction not yet in block", 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]) # ...or if the first tx is not fully-spent @@ -104,15 +103,15 @@ def run_test(self): # Test getblock heights including negatives relative to the head assert_equal(self.nodes[0].getblock("0")["height"], 0) - assert_raises(JSONRPCException, self.nodes[0].getblock, ["108"]) + assert_raises_message(JSONRPCException, "Block height out of range", self.nodes[0].getblock, "108") assert_equal(self.nodes[0].getblock("107")["height"], 107) assert_equal(self.nodes[0].getblock("-1")["height"], 107) assert_equal(self.nodes[0].getblock("-2")["height"], 106) assert_equal(self.nodes[0].getblock("-20")["height"], 88) assert_equal(self.nodes[0].getblock("-107")["height"], 1) assert_equal(self.nodes[0].getblock("-108")["height"], 0) - assert_raises(JSONRPCException, self.nodes[0].getblock, ["-109"]) - assert_raises(JSONRPCException, self.nodes[0].getblock, ["-0"]) + assert_raises_message(JSONRPCException, "Block height out of range", self.nodes[0].getblock, "-109") + assert_raises_message(JSONRPCException, "Invalid block height parameter", self.nodes[0].getblock, "-0") # Test getblockhash negative heights assert_equal(self.nodes[0].getblockhash(-1), self.nodes[0].getblockhash(107)) diff --git a/qa/rpc-tests/mining_shielded_coinbase.py b/qa/rpc-tests/mining_shielded_coinbase.py index 118ec4f9fe6..62c568d8668 100755 --- a/qa/rpc-tests/mining_shielded_coinbase.py +++ b/qa/rpc-tests/mining_shielded_coinbase.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -20,6 +20,7 @@ wait_and_assert_operationid_status, check_node_log, ) +from test_framework.zip317 import conventional_fee class ShieldCoinbaseTest (BitcoinTestFramework): @@ -30,7 +31,6 @@ def __init__(self): def start_node_with(self, index, extra_args=[]): args = [ - '-minrelaytxfee=0', nuparams(BLOSSOM_BRANCH_ID, 1), nuparams(HEARTWOOD_BRANCH_ID, 10), nuparams(CANOPY_BRANCH_ID, 20), @@ -96,16 +96,16 @@ def run_test (self): self.sync_all() # Transparent coinbase outputs are subject to coinbase maturity - assert_equal(self.nodes[0].getbalance(), Decimal('0')) - assert_equal(self.nodes[0].z_gettotalbalance()['transparent'], '0.00') - assert_equal(self.nodes[0].z_gettotalbalance()['private'], '0.00') - assert_equal(self.nodes[0].z_gettotalbalance()['total'], '0.00') + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('0')) + assert_equal(Decimal(self.nodes[0].z_gettotalbalance()['transparent']), Decimal('0')) + assert_equal(Decimal(self.nodes[0].z_gettotalbalance()['private']), Decimal('0')) + assert_equal(Decimal(self.nodes[0].z_gettotalbalance()['total']), Decimal('0')) # Shielded coinbase outputs are not subject to coinbase maturity - assert_equal(self.nodes[1].z_getbalance(node1_zaddr, 0), 5) - assert_equal(self.nodes[1].z_getbalance(node1_zaddr), 5) - assert_equal(self.nodes[1].z_gettotalbalance()['private'], '5.00') - assert_equal(self.nodes[1].z_gettotalbalance()['total'], '5.00') + assert_equal(Decimal(self.nodes[1].z_getbalance(node1_zaddr, 0)), Decimal('5')) + assert_equal(Decimal(self.nodes[1].z_getbalance(node1_zaddr)), Decimal('5')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()['private']), Decimal('5')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()['total']), Decimal('5')) # Send from Sapling coinbase to Sapling address and transparent address # (to check that a non-empty vout is allowed when spending shielded @@ -113,18 +113,20 @@ def run_test (self): print("Sending Sapling coinbase to Sapling address") node0_zaddr = self.nodes[0].z_getnewaddress('sapling') node0_taddr = self.nodes[0].getnewaddress() - recipients = [] - recipients.append({"address": node0_zaddr, "amount": Decimal('2')}) - recipients.append({"address": node0_taddr, "amount": Decimal('2')}) - myopid = self.nodes[1].z_sendmany(node1_zaddr, recipients, 1, 0, 'AllowRevealedRecipients') + fee = conventional_fee(3) + recipients = [ + {"address": node0_zaddr, "amount": Decimal('2')}, + {"address": node0_taddr, "amount": Decimal('2')}, + ] + myopid = self.nodes[1].z_sendmany(node1_zaddr, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() - assert_equal(self.nodes[0].z_getbalance(node0_zaddr), 2) - assert_equal(self.nodes[0].z_getbalance(node0_taddr), 2) - assert_equal(self.nodes[1].z_getbalance(node1_zaddr), 1) + assert_equal(Decimal(self.nodes[0].z_getbalance(node0_zaddr)), Decimal('2')) + assert_equal(Decimal(self.nodes[0].z_getbalance(node0_taddr)), Decimal('2')) + assert_equal(Decimal(self.nodes[1].z_getbalance(node1_zaddr)), Decimal('1') - fee) # Generate a Unified Address for node 1 self.nodes[1].z_getnewaccount() diff --git a/qa/rpc-tests/orchard_reorg.py b/qa/rpc-tests/orchard_reorg.py index 420118393ea..cbe32b229e0 100755 --- a/qa/rpc-tests/orchard_reorg.py +++ b/qa/rpc-tests/orchard_reorg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -19,11 +19,10 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import ZIP_317_FEE from finalsaplingroot import ORCHARD_TREE_EMPTY_ROOT -from decimal import Decimal - class OrchardReorgTest(BitcoinTestFramework): def __init__(self): super().__init__() @@ -32,7 +31,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(BLOSSOM_BRANCH_ID, 1), nuparams(HEARTWOOD_BRANCH_ID, 5), nuparams(CANOPY_BRANCH_ID, 5), @@ -67,9 +65,8 @@ def run_test(self): ) # 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) + res = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), ua, ZIP_317_FEE, None, None, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], res['opid']) # After mining a block, finalorchardroot should have changed. self.sync_all() @@ -92,9 +89,8 @@ def run_test(self): 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) + res = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), ua, ZIP_317_FEE, None, None, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], res['opid']) # Mine two blocks on node 0. print("Mining 2 blocks on node 0") diff --git a/qa/rpc-tests/p2p_txexpiringsoon.py b/qa/rpc-tests/p2p_txexpiringsoon.py index c0c127e5d51..22d0726b8d9 100755 --- a/qa/rpc-tests/p2p_txexpiringsoon.py +++ b/qa/rpc-tests/p2p_txexpiringsoon.py @@ -1,14 +1,18 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from decimal import Decimal + from test_framework.authproxy import JSONRPCException from test_framework.mininode import NodeConn, NetworkThread, CInv, \ msg_mempool, msg_getdata, msg_tx, mininode_lock, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, connect_nodes_bi, fail, \ p2p_port, start_nodes, sync_blocks, sync_mempools +from test_framework.zip317 import conventional_fee + from tx_expiry_helper import TestNode, create_transaction @@ -21,7 +25,6 @@ def __init__(self): def setup_network(self): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', ]] * self.num_nodes) connect_nodes_bi(self.nodes, 0, 1) @@ -31,7 +34,7 @@ def send_transaction(self, testnode, block, address, expiry_height): tx = create_transaction(self.nodes[0], block, address, - 10.0, + Decimal("10.0") - conventional_fee(2), expiry_height) testnode.send_message(msg_tx(tx)) diff --git a/qa/rpc-tests/prioritisetransaction.py b/qa/rpc-tests/prioritisetransaction.py index 41655590212..ac6022b41c2 100755 --- a/qa/rpc-tests/prioritisetransaction.py +++ b/qa/rpc-tests/prioritisetransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017 The Zcash developers +# Copyright (c) 2017-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -28,10 +28,10 @@ def setup_nodes(self): '-debug=zrpcunsafe', ] return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ + args + ['-txunpaidactionlimit=51', '-blockunpaidactionlimit=50'], + args + ['-txunpaidactionlimit=51', '-blockunpaidactionlimit=32'], args + ['-txunpaidactionlimit=51'], - args + ['-txunpaidactionlimit=51', '-blockunpaidactionlimit=25'], - args + ['-txunpaidactionlimit=51'], - args + ['-txunpaidactionlimit=25'], + args + ['-txunpaidactionlimit=32'], ]) def run_test(self): @@ -39,12 +39,17 @@ def run_test(self): # but the halving interval is only 144 blocks. # For the first test the miner subsidy is 10 ZEC. - self.test(self.nodes[0], Decimal("10"), DEFAULT_BLOCK_UNPAID_ACTION_LIMIT) + self.test(self.nodes[0], Decimal("10"), 50) assert_equal(153, self.nodes[0].getblockcount()) # For the second test the miner subsidy is 6.25 ZEC. # (The Founders' Reward has expired and there are no funding streams.) - self.test(self.nodes[1], Decimal("6.25"), 25) + self.test(self.nodes[1], Decimal("6.25"), 32) + assert_equal(288, self.nodes[0].getblockcount()) + + # For the third test the miner subsidy is 3.125 ZEC. + self.test(self.nodes[2], Decimal("3.125"), DEFAULT_BLOCK_UNPAID_ACTION_LIMIT) + assert_equal(392, self.nodes[0].getblockcount()) def test(self, mining_node, miner_subsidy, block_unpaid_action_limit): print("Testing with -blockunpaidactionlimit=%d" % (block_unpaid_action_limit,)) @@ -62,43 +67,61 @@ def eventually_in_template(txid): return False # Make sure we have enough mature funds on mining_node. - blocks = 100 + block_unpaid_action_limit + 2 + n = max(1, block_unpaid_action_limit) + blocks = 100 + n + 2 print("Mining %d blocks..." % (blocks,)) mining_node.generate(blocks) self.sync_all() - node2_initial_balance = self.nodes[2].getbalance() node3_initial_balance = self.nodes[3].getbalance() if block_unpaid_action_limit == 50: # Create a tx that will not be accepted to the mempool because it has # more unpaid actions than `-txunpaidactionlimit`. - amount = miner_subsidy * (block_unpaid_action_limit + 1) + amount = miner_subsidy * 51 assert_equal(amount + miner_subsidy, mining_node.getbalance()) - assert_raises_message(JSONRPCException, "tx unpaid action limit exceeded", + assert_raises_message(JSONRPCException, + "tx unpaid action limit exceeded: 52 action(s) exceeds limit of 51", mining_node.sendtoaddress, - self.nodes[2].getnewaddress(), amount) + self.nodes[3].getnewaddress(), amount) # Create a tx that will not be mined unless prioritised. - # We spend `block_unpaid_action_limit` mining rewards, ensuring that - # tx has exactly `block_unpaid_action_limit + 1` logical actions, - # because one extra input will be needed to pay the fee. + # We spend `n` mining rewards, ensuring that tx has exactly `n + 1` + # logical actions, because one extra input will be needed to pay the fee. + # # Since we've set `-paytxfee` to pay only the relay fee rate, the fee # will be less than the marginal fee, so these are all unpaid actions. # This transaction will be relayed to nodes 1 and 2 despite being over # the block unpaid action limit, because we set `-txunpaidactionlimit=51` # on nodes 0, 1, and 2. - amount = miner_subsidy * block_unpaid_action_limit + amount = miner_subsidy * n assert_equal(amount + miner_subsidy*2, mining_node.getbalance()) - tx = mining_node.sendtoaddress(self.nodes[2].getnewaddress(), amount) + tx = mining_node.sendtoaddress(self.nodes[3].getnewaddress(), amount) mempool = mining_node.getrawmempool(True) assert tx in mempool, mempool fee_zats = int(mempool[tx]['fee'] * COIN) assert fee_zats < MARGINAL_FEE, fee_zats + tx_verbose = mining_node.getrawtransaction(tx, 1) - assert_equal(block_unpaid_action_limit + 1, len(tx_verbose['vin'])) - # TODO after #6676: assert_equal(block_unpaid_action_limit + 1, tx_verbose['unpaidActions']) + t_in_actions = len(tx_verbose['vin']) + t_out_actions = len(tx_verbose['vout']) + assert_equal(n + 1, t_in_actions) + assert_equal(2, t_out_actions) + assert_equal([], tx_verbose['vjoinsplit']) + assert_equal([], tx_verbose['vShieldedSpend']) + assert_equal([], tx_verbose['vShieldedOutput']) + if tx_verbose['version'] >= 5: + assert_equal([], tx_verbose['orchard']['actions']) + else: + assert('orchard' not in tx_verbose) + + unpaid_actions = max(t_in_actions, t_out_actions) + assert_equal(unpaid_actions, n + 1) + # TODO after #6676: assert_equal(unpaid_actions, tx_verbose['unpaidActions']) + + # Calculate the effective fee we would need to satisfy the limit. + required_fee = (unpaid_actions - block_unpaid_action_limit) * MARGINAL_FEE # Check that tx is not in a new block template prior to prioritisation. block_template = mining_node.getblocktemplate() @@ -118,31 +141,34 @@ def sync_and_check(): time.sleep(1) sync_mempools(self.nodes[3:]) - # tx should not have been accepted to node3's mempool because that node has - # `-txunpaidactionlimit=25`, which is less than `block_unpaid_action_limit + 1`. - assert 25 < block_unpaid_action_limit + 1 + # For the first two tests, tx should not be accepted to node3's + # mempool because that node has `-txunpaidactionlimit=32`, which is + # less than `unpaid_actions` in those tests. For the third test, it + # should be accepted, but might already have been mined. mempool = self.nodes[3].getrawmempool(True) - assert tx not in mempool, mempool + if 32 < unpaid_actions: + assert tx not in mempool, mempool - # Prioritising it on node 2 has no effect on mining_node. + # Prioritising it on a node other than mining_node has no effect. + other_node = self.nodes[0 if mining_node == self.nodes[2] else 2] sync_and_check() - priority_success = self.nodes[2].prioritisetransaction(tx, 0, MARGINAL_FEE) + priority_success = other_node.prioritisetransaction(tx, 0, required_fee) assert(priority_success) - mempool = self.nodes[2].getrawmempool(True) - assert_equal(fee_zats + MARGINAL_FEE, mempool[tx]['modifiedfee'] * COIN) + mempool = other_node.getrawmempool(True) + assert_equal(fee_zats + required_fee, mempool[tx]['modifiedfee'] * COIN) sync_and_check() send_fully_paid_transaction() assert_equal(eventually_in_template(tx), False) # Putting a non-zero value in the obsolete "priority" field causes an error. assert_raises_message(JSONRPCException, "Priority is not supported", - self.nodes[2].prioritisetransaction, tx, 1, 0) + other_node.prioritisetransaction, tx, 1, 0) # Now prioritise it on mining_node, but short by one zatoshi. - priority_success = mining_node.prioritisetransaction(tx, 0, MARGINAL_FEE - fee_zats - 1) + priority_success = mining_node.prioritisetransaction(tx, 0, required_fee - fee_zats - 1) assert(priority_success) mempool = mining_node.getrawmempool(True) - assert_equal(MARGINAL_FEE - 1, mempool[tx]['modifiedfee'] * COIN) + assert_equal(required_fee - 1, mempool[tx]['modifiedfee'] * COIN) send_fully_paid_transaction() assert_equal(eventually_in_template(tx), False) @@ -152,7 +178,7 @@ def sync_and_check(): priority_success = mining_node.prioritisetransaction(tx, None, 1) assert(priority_success) mempool = mining_node.getrawmempool(True) - assert_equal(MARGINAL_FEE, mempool[tx]['modifiedfee'] * COIN) + assert_equal(required_fee, mempool[tx]['modifiedfee'] * COIN) # The block template will refresh after 1 minute, or after 5 seconds if a new # transaction is added to the mempool. As long as there is less than a minute @@ -164,18 +190,17 @@ def sync_and_check(): send_fully_paid_transaction() assert_equal(eventually_in_template(tx), True) - # Mine a block on node 0. + # Mine a block. blk_hash = mining_node.generate(1) block = mining_node.getblock(blk_hash[0]) assert_equal(tx in block['tx'], True) sync_and_check() - # Check that tx was mined and that node 1 received the funds. + # Check that tx was mined and that node 3 received the expected funds (including + # the amounts from the three calls to `send_fully_paid_transaction`). mempool = mining_node.getrawmempool() assert_equal(mempool, []) - assert_equal(self.nodes[2].getbalance(), node2_initial_balance + amount) - # Check that all of the fully paid transactions were mined. - assert_equal(self.nodes[3].getbalance(), node3_initial_balance + Decimal("0.3")) + assert_equal(self.nodes[3].getbalance(), node3_initial_balance + amount + Decimal("0.3")) if __name__ == '__main__': PrioritiseTransactionTest().main() diff --git a/qa/rpc-tests/regtest_signrawtransaction.py b/qa/rpc-tests/regtest_signrawtransaction.py index df9512b330a..d79868114c2 100755 --- a/qa/rpc-tests/regtest_signrawtransaction.py +++ b/qa/rpc-tests/regtest_signrawtransaction.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 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 ( - LEGACY_DEFAULT_FEE, start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import ZIP_317_FEE class RegtestSignrawtransactionTest (BitcoinTestFramework): @@ -33,7 +33,7 @@ def run_test(self): opid = self.nodes[1].z_sendmany( taddr, [{'address': zaddr1, 'amount': 1}], - 1, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent') + 1, ZIP_317_FEE, 'AllowFullyTransparent') wait_and_assert_operationid_status(self.nodes[1], opid) if __name__ == '__main__': diff --git a/qa/rpc-tests/remove_sprout_shielding.py b/qa/rpc-tests/remove_sprout_shielding.py index 99d82f7f0b7..fbe8bee14c3 100755 --- a/qa/rpc-tests/remove_sprout_shielding.py +++ b/qa/rpc-tests/remove_sprout_shielding.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2020 The Zcash developers +# Copyright (c) 2020-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -17,11 +17,11 @@ CANOPY_BRANCH_ID, NU5_BRANCH_ID, ) +from test_framework.zip317 import ZIP_317_FEE import logging HAS_CANOPY = [ - '-minrelaytxfee=0', '-nurejectoldversions=false', '-anchorconfirmations=1', nuparams(BLOSSOM_BRANCH_ID, 205), @@ -69,7 +69,7 @@ def run_test(self): n0_taddr0 = self.nodes[0].getnewaddress() for _ in range(3): recipients = [{"address": n0_taddr0, "amount": Decimal('1')}] - myopid = self.nodes[0].z_sendmany(n0_sprout_addr0, recipients, 1, 0, 'AllowRevealedRecipients') + myopid = self.nodes[0].z_sendmany(n0_sprout_addr0, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) @@ -82,14 +82,14 @@ def run_test(self): JSONRPCException, "Sending funds into the Sprout pool is no longer supported.", self.nodes[0].z_mergetoaddress, - ["ANY_TADDR"], n1_sprout_addr0, 0) + ["ANY_TADDR"], n1_sprout_addr0, ZIP_317_FEE) self.nodes[0].generate(1) self.sync_all() # Send some funds back to n0_taddr0 recipients = [{"address": n0_taddr0, "amount": Decimal('1')}] - myopid = self.nodes[0].z_sendmany(n0_sprout_addr0, recipients, 1, 0, 'AllowRevealedRecipients') + myopid = self.nodes[0].z_sendmany(n0_sprout_addr0, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], myopid) # Mine to one block before Canopy activation on node 0; adding value @@ -114,7 +114,7 @@ def run_test(self): # Create taddr -> Sprout z_sendmany transaction on node 0. Should fail n1_sprout_addr1 = self.nodes[1].z_getnewaddress('sprout') recipients = [{"address": n1_sprout_addr1, "amount": Decimal('1')}] - myopid = self.nodes[0].z_sendmany(n0_taddr0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(n0_taddr0, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", unsupported_sprout_msg) print("taddr -> Sprout z_sendmany tx rejected at Canopy activation on node 0") @@ -139,7 +139,7 @@ def run_test(self): # Shield coinbase to Sapling on node 0. Should pass sapling_addr = self.nodes[0].z_getnewaddress('sapling') - myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sapling_addr, 0)['opid'] + myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sapling_addr, ZIP_317_FEE)['opid'] wait_and_assert_operationid_status(self.nodes[0], myopid) print("taddr -> Sapling z_shieldcoinbase tx accepted after Canopy on node 0") diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index f96dc3a53d9..db724a1a7de 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -13,6 +13,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee class ShorterBlockTimes(BitcoinTestFramework): @@ -23,7 +24,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(BLOSSOM_BRANCH_ID, 106), '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_gettotalbalance', @@ -39,14 +39,15 @@ def run_test(self): node0_taddr = get_coinbase_address(self.nodes[0]) node0_zaddr = self.nodes[0].z_getnewaddress('sapling') - recipients = [{'address': node0_zaddr, 'amount': Decimal('10.0')}] - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, 0, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{'address': node0_zaddr, 'amount': Decimal('10.0') - fee}] + myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, fee, 'AllowRevealedSenders') txid = wait_and_assert_operationid_status(self.nodes[0], myopid) assert_equal(105, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # Blossom activation - 1 self.sync_all() self.nodes[0].generate(1) self.sync_all() - assert_equal(10, Decimal(self.nodes[0].z_gettotalbalance()['private'])) + assert_equal(10 - fee, Decimal(self.nodes[0].z_gettotalbalance()['private'])) self.nodes[0].generate(2) self.sync_all() @@ -65,13 +66,13 @@ def run_test(self): assert_equal(15, self.nodes[1].getwalletinfo()['immature_balance']) # Send and mine a transaction after activation - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, 0, 'AllowRevealedSenders') + myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, fee, 'AllowFullyTransparent') txid = wait_and_assert_operationid_status(self.nodes[0], myopid) assert_equal(147, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # height + 1 + 40 self.sync_all() # Ensure the transaction has propagated to node 1 self.nodes[1].generate(1) self.sync_all() - assert_equal(20, Decimal(self.nodes[0].z_gettotalbalance()['private'])) + assert_equal(20 - fee*2, Decimal(self.nodes[0].z_gettotalbalance()['private'])) if __name__ == '__main__': diff --git a/qa/rpc-tests/show_help.py b/qa/rpc-tests/show_help.py index 69597cf95a8..b1eab378af8 100755 --- a/qa/rpc-tests/show_help.py +++ b/qa/rpc-tests/show_help.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2017-2022 The Zcash developers +# Copyright (c) 2017-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -502,7 +502,7 @@ -txunpaidactionlimit= Transactions with more than this number of unpaid actions will not be - accepted to the mempool or relayed (default: 50) + accepted to the mempool or relayed (default: 0) Block creation options: @@ -511,7 +511,7 @@ -blockunpaidactionlimit= Set the limit on unpaid actions that will be accepted in a block for - transactions paying less than the ZIP 317 fee (default: 50) + transactions paying less than the ZIP 317 fee (default: 0) | -blockversion= | Override block version to test forking scenarios (default: 4) diff --git a/qa/rpc-tests/signrawtransaction_offline.py b/qa/rpc-tests/signrawtransaction_offline.py index 8927c6eb7d5..5f58f70c7a5 100755 --- a/qa/rpc-tests/signrawtransaction_offline.py +++ b/qa/rpc-tests/signrawtransaction_offline.py @@ -1,15 +1,18 @@ #!/usr/bin/env python3 +# Copyright (c) 2018-2024 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, - LEGACY_DEFAULT_FEE, assert_equal, assert_true, initialize_chain_clean, nuparams, start_node, ) +from test_framework.zip317 import conventional_fee from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -49,7 +52,7 @@ def run_test(self): create_inputs = [{'txid': txid, 'vout': 0}] sign_inputs = [{'txid': txid, 'vout': 0, 'scriptPubKey': scriptpubkey, 'amount': 10}] - create_hex = self.nodes[0].createrawtransaction(create_inputs, {taddr: Decimal('10.0') - LEGACY_DEFAULT_FEE}) + create_hex = self.nodes[0].createrawtransaction(create_inputs, {taddr: Decimal('10.0') - conventional_fee(2)}) # An offline regtest node does not rely on the approx release height of the software # to determine the consensus rules to be used for signing. diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index aee4370cb76..1fec8a667f7 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -7,7 +7,8 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_true, \ start_nodes, \ - wait_and_assert_operationid_status_result, LEGACY_DEFAULT_FEE + wait_and_assert_operationid_status_result +from test_framework.zip317 import conventional_fee SAPLING_ADDR = 'zregtestsapling1ssqj3f3majnl270985gqcdqedd9t4nlttjqskccwevj2v20sc25deqspv3masufnwcdy67cydyy' SAPLING_KEY = 'secret-extended-key-regtest1qv62zt2fqyqqpqrh2qzc08h7gncf4447jh9kvnnnhjg959fkwt7mhw9j8e9at7attx8z6u3953u86vcnsujdc2ckdlcmztjt44x3uxpah5mxtncxd0mqcnz9eq8rghh5m4j44ep5d9702sdvvwawqassulktfegrcp4twxgqdxx4eww3lau0mywuaeztpla2cmvagr5nj98elt45zh6fjznadl6wz52n2uyhdwcm2wlsu8fnxstrk6s4t55t8dy6jkgx5g0cwpchh5qffp8x5' @@ -127,7 +128,8 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height, sprou # Check that unmigrated amount + unfinalized = starting balance - fee status = node.z_getmigrationstatus() print("status: {}".format(status)) - assert_equal(sprout_initial_balance - LEGACY_DEFAULT_FEE, Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) + fee = conventional_fee(4) + assert_equal(sprout_initial_balance - fee, Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) # The transaction in the mempool should be the one listed in migration_txids, # and it should expire at the next 450 % 500. @@ -146,7 +148,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height, sprou print("sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance)) assert_true(sprout_balance < sprout_initial_balance, "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") - assert_true(sprout_balance + sapling_balance, sprout_initial_balance - LEGACY_DEFAULT_FEE) + assert_true(sprout_balance + sapling_balance, sprout_initial_balance - fee) check_migration_status(node, saplingAddr, DURING_MIGRATION) # At 10 % 500 the transactions will be considered 'finalized' diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 9c6fa430d2d..61572825364 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # blocktools.py - utilities for manipulating blocks and transactions # Copyright (c) 2015-2016 The Bitcoin Core developers -# Copyright (c) 2017-2022 The Zcash developers +# Copyright (c) 2017-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -101,10 +101,10 @@ def create_coinbase(height, pubkey=None, after_blossom=False, outputs=[], lockbo # Create a transaction with an anyone-can-spend output, that spends the # nth output of prevtx. -def create_transaction(prevtx, n, sig, value): +def create_transaction(prevtx, n, sig, value_zats): tx = CTransaction() assert(n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) - tx.vout.append(CTxOut(value, b"")) + tx.vout.append(CTxOut(value_zats, b"")) tx.calc_sha256() return tx diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index fd39336592f..2481baa3f65 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -31,8 +31,6 @@ ZCASHD_BINARY = os.path.join('src', 'zcashd') -LEGACY_DEFAULT_FEE = Decimal('0.00001') - COVERAGE_DIR = None PRE_BLOSSOM_BLOCK_TARGET_SPACING = 150 POST_BLOSSOM_BLOCK_TARGET_SPACING = 75 diff --git a/qa/rpc-tests/test_framework/zip317.py b/qa/rpc-tests/test_framework/zip317.py index 7e8cd904a7b..9adb2ad3357 100644 --- a/qa/rpc-tests/test_framework/zip317.py +++ b/qa/rpc-tests/test_framework/zip317.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2023 The Zcash developers +# Copyright (c) 2023-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -19,6 +19,9 @@ # https://zips.z.cash/zip-0317#fee-calculation. GRACE_ACTIONS = 2 +# The minimum ZIP 317 fee. +MINIMUM_FEE = MARGINAL_FEE * GRACE_ACTIONS + # Limits the relative probability of picking a given transaction to be at most `WEIGHT_RATIO_CAP` # times greater than a transaction that pays exactly the conventional fee. See # https://zips.z.cash/zip-0317#recommended-algorithm-for-block-template-construction @@ -26,7 +29,7 @@ # Default limit on the number of unpaid actions in a block. See # https://zips.z.cash/zip-0317#recommended-algorithm-for-block-template-construction -DEFAULT_BLOCK_UNPAID_ACTION_LIMIT = 50 +DEFAULT_BLOCK_UNPAID_ACTION_LIMIT = 0 # The zcashd RPC sentinel value to indicate the conventional_fee when a positional argument is # required. diff --git a/qa/rpc-tests/turnstile.py b/qa/rpc-tests/turnstile.py index e904c4dac63..9b9343ee6ea 100755 --- a/qa/rpc-tests/turnstile.py +++ b/qa/rpc-tests/turnstile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -38,10 +38,11 @@ bitcoind_processes, check_node_log ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE + from decimal import Decimal BASE_ARGS = [ - '-minrelaytxfee=0', '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', ] @@ -91,14 +92,14 @@ def run_test(self): self.sync_all() taddr0 = get_coinbase_address(self.nodes[0]) + fee = conventional_fee(3) if (POOL_NAME == "SPROUT"): dest_addr = self.nodes[0].listaddresses()[0]['sprout']['addresses'][0] elif (POOL_NAME == "SAPLING"): # Node 0 shields some funds dest_addr = self.nodes[0].z_getnewaddress('sapling') - recipients = [] - recipients.append({"address": dest_addr, "amount": Decimal('50')}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0) + recipients = [{"address": dest_addr, "amount": Decimal('50') - fee}] + myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], myopid) else: fail("Unrecognized pool name: " + POOL_NAME) @@ -121,9 +122,8 @@ def run_test(self): self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('200')) # Node 0 creates an unshielding transaction - recipients = [] - recipients.append({"address": taddr0, "amount": Decimal('1')}) - myopid = self.nodes[0].z_sendmany(dest_addr, recipients, 1, 0, 'AllowRevealedRecipients') + recipients = [{"address": taddr0, "amount": Decimal('1')}] + myopid = self.nodes[0].z_sendmany(dest_addr, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) # Verify transaction appears in mempool of nodes @@ -170,8 +170,8 @@ def run_test(self): # Verify size of shielded pool self.assert_pool_balance(self.nodes[0], POOL_NAME.lower(), Decimal('0')) - self.assert_pool_balance(self.nodes[1], POOL_NAME.lower(), Decimal('199')) - self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('199')) + self.assert_pool_balance(self.nodes[1], POOL_NAME.lower(), Decimal('199') - fee) + self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('199') - fee) # Stop node 0 and check logs to verify the block was rejected as a turnstile violation string_to_find1 = "ConnectBlock: turnstile violation in " + POOL_NAME.capitalize() + " shielded value pool" diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py index 3e55edb4a90..3d06f79b045 100755 --- a/qa/rpc-tests/txn_doublespend.py +++ b/qa/rpc-tests/txn_doublespend.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -16,6 +16,7 @@ sync_blocks, gather_inputs, ) +from test_framework.zip317 import conventional_fee class TxnMallTest(BitcoinTestFramework): @@ -26,7 +27,6 @@ def add_options(self, parser): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', ]] * self.num_nodes) @@ -48,10 +48,12 @@ def run_test(self): # First: use raw transaction API to send (starting_balance - (mining_reward - 2)) ZEC to node1_address, # but don't broadcast: (total_in, inputs) = gather_inputs(self.nodes[0], (starting_balance - (mining_reward - 2))) + fee = conventional_fee(25) change_address = self.nodes[0].getnewaddress("") - outputs = {} - outputs[change_address] = (mining_reward - 2) - outputs[node1_address] = (starting_balance - (mining_reward - 2)) + outputs = { + change_address: mining_reward - 2 - fee, + node1_address: starting_balance - (mining_reward - 2), + } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) doublespend = self.nodes[0].signrawtransaction(rawtx) assert_equal(doublespend["complete"], True) @@ -82,7 +84,7 @@ def run_test(self): assert_equal(tx1["confirmations"], 1) assert_equal(tx2["confirmations"], 1) # Node1's total balance should be its starting balance plus both transaction amounts: - assert_equal(self.nodes[1].getbalance("*"), starting_balance - (tx1["amount"]+tx2["amount"])) + assert_equal(self.nodes[1].getbalance("*"), starting_balance - (tx1["amount"] + tx2["amount"])) else: assert_equal(tx1["confirmations"], 0) assert_equal(tx2["confirmations"], 0) @@ -105,9 +107,9 @@ def run_test(self): assert_equal(tx1["confirmations"], -1) assert_equal(tx2["confirmations"], -1) - # Node0's total balance should be starting balance, plus (mining_reward * 2) for - # two more matured blocks, minus (starting_balance - (mining_reward - 2)) for the double-spend: - expected = starting_balance + (mining_reward * 2) - (starting_balance - (mining_reward - 2)) + # Node0's total balance should be starting balance, plus (mining_reward * 2) for two more + # matured blocks, minus (starting_balance - (mining_reward - 2) + fee) for the double-spend. + expected = starting_balance + (mining_reward * 2) - (starting_balance - (mining_reward - 2) + fee) assert_equal(self.nodes[0].getbalance(), expected) assert_equal(self.nodes[0].getbalance("*"), expected) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index bac5d5b2b08..bda68b2d337 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 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.mininode import COIN from test_framework.util import assert_equal, start_nodes, start_node, \ connect_nodes_bi, sync_blocks, sync_mempools from test_framework.zip317 import conventional_fee @@ -21,7 +22,6 @@ def __init__(self): def setup_network(self, split=False): self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getbalance', ]] * 3) @@ -31,15 +31,15 @@ def setup_network(self, split=False): self.is_network_split=False self.sync_all() - def run_test (self): + 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) + assert_equal(Decimal(walletinfo['immature_balance']), Decimal('40')) + assert_equal(Decimal(walletinfo['balance']), Decimal('0')) blockchaininfo = self.nodes[0].getblockchaininfo() assert_equal(blockchaininfo['estimatedheight'], 4) @@ -48,20 +48,20 @@ def run_test (self): 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(), 0) - assert_equal(self.nodes[0].getbalance("*"), 40) - assert_equal(self.nodes[1].getbalance("*"), 10) - assert_equal(self.nodes[2].getbalance("*"), 0) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('40')) + assert_equal(Decimal(self.nodes[1].getbalance()), Decimal('10')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('0')) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('40')) + assert_equal(Decimal(self.nodes[1].getbalance("*")), Decimal('10')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('0')) # Send 21 ZEC from 0 to 2 using sendtoaddress call. # Second transaction will be child of first, and will require a fee - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal('11')) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal('10')) walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 0) + assert_equal(Decimal(walletinfo['immature_balance']), Decimal('0')) blockchaininfo = self.nodes[0].getblockchaininfo() assert_equal(blockchaininfo['estimatedheight'], 105) @@ -77,10 +77,10 @@ def run_test (self): # node0 should end up with 50 ZEC in block rewards plus fees, but # minus the 21 ZEC plus fees sent to node2 - assert_equal(self.nodes[0].getbalance(), 50-21) - assert_equal(self.nodes[2].getbalance(), 21) - assert_equal(self.nodes[0].getbalance("*"), 50-21) - assert_equal(self.nodes[2].getbalance("*"), 21) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('50') - Decimal('21')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('21')) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('50') - Decimal('21')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('21')) # Node0 should have three unspent outputs. # Create a couple of transactions to send them to node2, submit them through @@ -102,16 +102,14 @@ def run_test (self): # Catch an attempt to send a transaction with an absurdly high fee. # Send 1.0 ZEC from an utxo of value 10.0 ZEC but don't specify a change output, so then - # the change of 9.0 ZEC becomes the fee, which is considered to be absurdly high because - # the fee is more than 4 times the conventional fee. - assert(Decimal("9.0") > 4*conventional_fee(1)) + # the change of 9.0 ZEC becomes the fee, which is considered to be absurdly high. inputs = [] outputs = {} for utxo in node2utxos: if utxo["amount"] == Decimal("10.0"): break assert_equal(utxo["amount"], Decimal("10.0")) - inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]}) + inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) outputs[self.nodes[2].getnewaddress("")] = Decimal("1.0") raw_tx = self.nodes[2].createrawtransaction(inputs, outputs) signed_tx = self.nodes[2].signrawtransaction(raw_tx) @@ -123,11 +121,12 @@ def run_test (self): # create both transactions txns_to_send = [] + fee = conventional_fee(2) for utxo in node0utxos: inputs = [] outputs = {} - inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]}) - outputs[self.nodes[2].getnewaddress("")] = utxo["amount"] + inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) + outputs[self.nodes[2].getnewaddress("")] = utxo["amount"] - fee raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx)) @@ -141,52 +140,52 @@ def run_test (self): self.nodes[1].generate(1) self.sync_all() - assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[2].getbalance(), 50) - assert_equal(self.nodes[0].getbalance("*"), 0) - assert_equal(self.nodes[2].getbalance("*"), 50) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('0')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('50') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('0')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('50') - 3*fee) # Send 10 ZEC normally address = self.nodes[0].getnewaddress("") self.nodes[2].settxfee(Decimal('0.001')) # not the default - self.nodes[2].sendtoaddress(address, 10, "", "", False) + self.nodes[2].sendtoaddress(address, Decimal('10'), "", "", False) self.sync_all() self.nodes[2].generate(1) self.sync_all() - assert_equal(self.nodes[2].getbalance(), Decimal('39.99900000')) - assert_equal(self.nodes[0].getbalance(), Decimal('10.00000000')) - assert_equal(self.nodes[2].getbalance("*"), Decimal('39.99900000')) - assert_equal(self.nodes[0].getbalance("*"), Decimal('10.00000000')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('39.99900000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('10.00000000')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('39.99900000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('10.00000000')) # Send 10 ZEC with subtract fee from amount - self.nodes[2].sendtoaddress(address, 10, "", "", True) + self.nodes[2].sendtoaddress(address, Decimal('10'), "", "", True) self.sync_all() self.nodes[2].generate(1) self.sync_all() - assert_equal(self.nodes[2].getbalance(), Decimal('29.99900000')) - assert_equal(self.nodes[0].getbalance(), Decimal('19.99900000')) - assert_equal(self.nodes[2].getbalance("*"), Decimal('29.99900000')) - assert_equal(self.nodes[0].getbalance("*"), Decimal('19.99900000')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('29.99900000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('19.99900000')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('29.99900000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('19.99900000')) # Sendmany 10 ZEC - self.nodes[2].sendmany("", {address: 10}, 0, "", []) + self.nodes[2].sendmany("", {address: Decimal('10')}, 0, "", []) self.sync_all() self.nodes[2].generate(1) self.sync_all() - assert_equal(self.nodes[2].getbalance(), Decimal('19.99800000')) - assert_equal(self.nodes[0].getbalance(), Decimal('29.99900000')) - assert_equal(self.nodes[2].getbalance("*"), Decimal('19.99800000')) - assert_equal(self.nodes[0].getbalance("*"), Decimal('29.99900000')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('19.99800000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('29.99900000')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('19.99800000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('29.99900000')) # Sendmany 10 ZEC with subtract fee from amount - self.nodes[2].sendmany("", {address: 10}, 0, "", [address]) + self.nodes[2].sendmany("", {address: Decimal('10')}, 0, "", [address]) self.sync_all() self.nodes[2].generate(1) self.sync_all() - assert_equal(self.nodes[2].getbalance(), Decimal('9.99800000')) - assert_equal(self.nodes[0].getbalance(), Decimal('39.99800000')) - assert_equal(self.nodes[2].getbalance("*"), Decimal('9.99800000')) - assert_equal(self.nodes[0].getbalance("*"), Decimal('39.99800000')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('9.99800000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('39.99800000')) + assert_equal(Decimal(self.nodes[2].getbalance("*")), Decimal('9.99800000') - 3*fee) + assert_equal(Decimal(self.nodes[0].getbalance("*")), Decimal('39.99800000')) # Test ResendWalletTransactions: # Create a couple of transactions, then start up a fourth @@ -207,16 +206,16 @@ def run_test (self): assert(txid1 in self.nodes[3].getrawmempool()) # check integer balances from getbalance - assert_equal(self.nodes[2].getbalance("*", 1, False, True), 999800000) + assert_equal(Decimal(self.nodes[2].getbalance("*", 1, False, True)), 999800000 - 3*fee*COIN) # send from node 0 to node 2 taddr mytaddr = self.nodes[2].getnewaddress() - mytxid = self.nodes[0].sendtoaddress(mytaddr, 10.0) + mytxid = self.nodes[0].sendtoaddress(mytaddr, Decimal('10.0')) self.sync_all() self.nodes[0].generate(1) self.sync_all() - mybalance = self.nodes[2].z_getbalance(mytaddr) + mybalance = Decimal(self.nodes[2].z_getbalance(mytaddr)) assert_equal(mybalance, Decimal('10.0')) # check integer balances from z_getbalance diff --git a/qa/rpc-tests/wallet_1941.py b/qa/rpc-tests/wallet_1941.py index d9bcb405f16..0005c435cd9 100755 --- a/qa/rpc-tests/wallet_1941.py +++ b/qa/rpc-tests/wallet_1941.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,7 +9,8 @@ from test_framework.util import assert_equal, initialize_chain_clean, \ initialize_datadir, start_nodes, start_node, connect_nodes_bi, \ bitcoind_processes, wait_and_assert_operationid_status, \ - get_coinbase_address, LEGACY_DEFAULT_FEE + get_coinbase_address +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -67,9 +68,9 @@ def run_test (self): myzaddr = self.nodes[0].z_getnewaddress() # Send 10 coins to our zaddr. - recipients = [] - recipients.append({"address":myzaddr, "amount":Decimal('10.0') - LEGACY_DEFAULT_FEE}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": myzaddr, "amount": Decimal('10.0') - fee}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[0].generate(1) @@ -82,7 +83,7 @@ def run_test (self): # Confirm the balance on node 0. resp = self.nodes[0].z_getbalance(myzaddr) - assert_equal(Decimal(resp), Decimal('10.0') - LEGACY_DEFAULT_FEE) + assert_equal(Decimal(resp), Decimal('10.0') - fee) # Export the key for the zaddr from node 0. key = self.nodes[0].z_exportkey(myzaddr) @@ -109,7 +110,7 @@ def run_test (self): # Confirm that the balance on node 1 is valid now (node 1 must # have rescanned) resp = self.nodes[1].z_getbalance(myzaddr) - assert_equal(Decimal(resp), Decimal('10.0') - LEGACY_DEFAULT_FEE) + assert_equal(Decimal(resp), Decimal('10.0') - fee) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_accounts.py b/qa/rpc-tests/wallet_accounts.py index bf5f657e4b3..e9d8b2f03ec 100755 --- a/qa/rpc-tests/wallet_accounts.py +++ b/qa/rpc-tests/wallet_accounts.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -16,6 +16,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -23,7 +24,6 @@ class WalletAccountsTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 210), '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', @@ -141,9 +141,11 @@ def run_test(self): # 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') + coinbase_fee = conventional_fee(3) + recipients = [{'address': ua0, 'amount': Decimal('10') - coinbase_fee}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') txid = wait_and_assert_operationid_status(self.nodes[0], opid) + ua0sapling_balance = Decimal('10') - coinbase_fee # The wallet should detect the new note as belonging to the UA. tx_details = self.nodes[0].z_viewtransaction(txid) @@ -155,21 +157,23 @@ def run_test(self): # visible with minconf=0. self.sync_all() self.check_balance(0, 0, ua0, {}) - self.check_balance(0, 0, ua0, {'sapling': 10}, 0) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance}, 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}) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance}) # Send Sapling funds from the UA. print('Sending account funds to Sapling address') node1sapling = self.nodes[1].z_getnewaddress('sapling') + fee = conventional_fee(2) recipients = [{'address': node1sapling, 'amount': Decimal('1')}] - opid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, fee) txid = wait_and_assert_operationid_status(self.nodes[0], opid) + ua0sapling_balance -= Decimal('1') + fee # The wallet should detect the spent note as belonging to the UA. tx_details = self.nodes[0].z_viewtransaction(txid) @@ -183,7 +187,7 @@ def run_test(self): # 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) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance}, 0) # Activate NU5 print('Activating NU5') @@ -193,9 +197,11 @@ def run_test(self): # 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') + fee = conventional_fee(3) + recipients = [{'address': ua0, 'amount': Decimal('10') - fee}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, fee, 'AllowRevealedSenders') txid = wait_and_assert_operationid_status(self.nodes[0], opid) + ua0orchard_balance = Decimal('10') - fee # The wallet should detect the new note as belonging to the UA. tx_details = self.nodes[0].z_viewtransaction(txid) @@ -206,12 +212,12 @@ def run_test(self): # 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) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance}) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance, 'orchard': ua0orchard_balance}, 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']) + assert_equal(Decimal(self.nodes[0].z_gettotalbalance()['private']), ua0sapling_balance) + assert_equal(Decimal(self.nodes[0].z_gettotalbalance(0)['private']), ua0sapling_balance + ua0orchard_balance) self.nodes[2].generate(1) self.sync_all() @@ -223,9 +229,11 @@ def run_test(self): self.check_z_listaccounts(1, 0, 0, node1orchard) node1orchard = node1orchard['address'] + fee = conventional_fee(2) recipients = [{'address': node1orchard, 'amount': Decimal('1')}] - opid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, fee) txid = wait_and_assert_operationid_status(self.nodes[0], opid) + ua0orchard_balance -= Decimal('1') + fee # The wallet should detect the spent note as belonging to the UA. tx_details = self.nodes[0].z_viewtransaction(txid) @@ -248,8 +256,8 @@ def run_test(self): # 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) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance}) + self.check_balance(0, 0, ua0, {'sapling': ua0sapling_balance, 'orchard': ua0orchard_balance}, 0) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_anchorfork.py b/qa/rpc-tests/wallet_anchorfork.py index d8bd8cda5e0..3009d7dab8f 100755 --- a/qa/rpc-tests/wallet_anchorfork.py +++ b/qa/rpc-tests/wallet_anchorfork.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -7,7 +7,9 @@ from test_framework.util import assert_equal, initialize_chain_clean, \ start_nodes, stop_nodes, connect_nodes_bi, \ wait_and_assert_operationid_status, wait_bitcoinds, get_coinbase_address, \ - sync_blocks, sync_mempools, LEGACY_DEFAULT_FEE + sync_blocks, sync_mempools +from test_framework.zip317 import conventional_fee + from decimal import Decimal class WalletAnchorForkTest (BitcoinTestFramework): @@ -51,9 +53,9 @@ def run_test (self): # Node 0 creates a joinsplit transaction mytaddr0 = get_coinbase_address(self.nodes[0]) myzaddr0 = self.nodes[0].z_getnewaddress() - recipients = [] - recipients.append({"address":myzaddr0, "amount": Decimal('10.0') - LEGACY_DEFAULT_FEE}) - myopid = self.nodes[0].z_sendmany(mytaddr0, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": myzaddr0, "amount": Decimal('10.0') - fee}] + myopid = self.nodes[0].z_sendmany(mytaddr0, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) # Sync up mempools and mine the transaction. All nodes have the same anchor. @@ -75,9 +77,9 @@ def run_test (self): self.nodes[1].generate(1) # Partition A, node 0 creates a joinsplit transaction - recipients = [] - recipients.append({"address":myzaddr0, "amount": Decimal('10.0') - LEGACY_DEFAULT_FEE}) - myopid = self.nodes[0].z_sendmany(mytaddr0, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{"address": myzaddr0, "amount": Decimal('10.0') - fee}] + myopid = self.nodes[0].z_sendmany(mytaddr0, recipients, 1, fee, 'AllowRevealedSenders') txid = wait_and_assert_operationid_status(self.nodes[0], myopid) rawhex = self.nodes[0].getrawtransaction(txid) diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py index 4f8e12ae8ab..95a0119b3f3 100755 --- a/qa/rpc-tests/wallet_changeaddresses.py +++ b/qa/rpc-tests/wallet_changeaddresses.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 The Zcash developers +# Copyright (c) 2019-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -13,6 +13,7 @@ start_node, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -25,7 +26,6 @@ def setup_chain(self): def setup_network(self): args = [ - '-minrelaytxfee=0', nuparams(SAPLING_BRANCH_ID, 1), '-txindex', # Avoid JSONRPC error: No information available about transaction '-allowdeprecated=getnewaddress', @@ -43,30 +43,32 @@ def run_test(self): # Obtain some transparent funds midAddr = self.nodes[0].z_getnewaddress('sapling') - myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), midAddr, 0)['opid'] + coinbase_fee = conventional_fee(12) + myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), midAddr, coinbase_fee)['opid'] wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) self.sync_all() + taddrSource = self.nodes[0].getnewaddress() + recipients = [{"address": taddrSource, "amount": Decimal('2')}] for _ in range(6): - recipients = [{"address": taddrSource, "amount": Decimal('2')}] - myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, 0, 'AllowRevealedRecipients') + myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) self.sync_all() - def check_change_taddr_reuse(target, policy): + def check_change_taddr_reuse(target, fee, policy): recipients = [{"address": target, "amount": Decimal('1')}] # Send funds to recipient address twice - myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0, policy) + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, fee, policy) txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() - myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0, policy) + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, fee, policy) txid2 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() @@ -88,10 +90,10 @@ def check_change_taddr_reuse(target, policy): print() print('Checking z_sendmany(taddr->Sapling)') - check_change_taddr_reuse(saplingAddr, 'AllowFullyTransparent') + check_change_taddr_reuse(saplingAddr, conventional_fee(3), 'AllowFullyTransparent') print() print('Checking z_sendmany(taddr->taddr)') - check_change_taddr_reuse(taddr, 'AllowFullyTransparent') + check_change_taddr_reuse(taddr, conventional_fee(1), 'AllowFullyTransparent') if __name__ == '__main__': WalletChangeAddressesTest().main() diff --git a/qa/rpc-tests/wallet_changeindicator.py b/qa/rpc-tests/wallet_changeindicator.py index bf289ac8601..c3a9811bd90 100755 --- a/qa/rpc-tests/wallet_changeindicator.py +++ b/qa/rpc-tests/wallet_changeindicator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -11,6 +11,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -23,7 +24,6 @@ def generate_and_sync(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', ]] * self.num_nodes) @@ -34,16 +34,16 @@ def run_test(self): zaddr1 = self.nodes[1].z_getnewaddress() zaddr2 = self.nodes[1].z_getnewaddress() - self.nodes[0].sendtoaddress(taddr, Decimal('1.0')) + fee = conventional_fee(3) + self.nodes[0].sendtoaddress(taddr, Decimal('1.0') + fee) self.generate_and_sync() # Send 1 ZEC to a zaddr - wait_and_assert_operationid_status( - self.nodes[1], - self.nodes[1].z_sendmany( - taddr, - [{'address': zaddr1, 'amount': 1.0, 'memo': 'c0ffee01'}], - 1, 0, 'AllowRevealedSenders')) + opid = self.nodes[1].z_sendmany(taddr, + [{'address': zaddr1, 'amount': Decimal('1.0'), 'memo': 'c0ffee01'}], + 1, fee, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[1], opid) + self.generate_and_sync() # Check that we have received 1 note which is not change @@ -55,14 +55,17 @@ def run_test(self): assert_false(listunspent[0]['change'], "Unspent note should not be change") # Generate some change - wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6, 'memo': 'c0ffee02'}], 1, 0)) + fee = conventional_fee(2) + recipients = [{'address': zaddr2, 'amount': Decimal('0.6'), 'memo': 'c0ffee02'}] + opid = self.nodes[1].z_sendmany(zaddr1, recipients, 1, fee) + wait_and_assert_operationid_status(self.nodes[1], opid) self.generate_and_sync() # Check zaddr1 received sortedreceived1 = sorted(self.nodes[1].z_listreceivedbyaddress(zaddr1, 0), key = lambda received: received['amount']) assert_equal(2, len(sortedreceived1), "zaddr1 Should have received 2 notes") - assert_equal(Decimal('0.4'), sortedreceived1[0]['amount']) - assert_true(sortedreceived1[0]['change'], "Note valued at 0.4 should be change") + assert_equal(Decimal('0.4') - fee, sortedreceived1[0]['amount']) + assert_true(sortedreceived1[0]['change'], "Note valued at 0.4 - fee should be change") assert_equal(Decimal('1.0'), sortedreceived1[1]['amount']) assert_false(sortedreceived1[1]['change'], "Note valued at 1.0 should not be change") # Check zaddr2 received @@ -73,8 +76,8 @@ def run_test(self): # Check unspent sortedunspent = sorted(self.nodes[1].z_listunspent(), key = lambda received: received['amount']) assert_equal(2, len(sortedunspent), "Should have 2 unspent notes") - assert_equal(Decimal('0.4'), sortedunspent[0]['amount']) - assert_true(sortedunspent[0]['change'], "Unspent note valued at 0.4 should be change") + assert_equal(Decimal('0.4') - fee, sortedunspent[0]['amount']) + assert_true(sortedunspent[0]['change'], "Unspent note valued at 0.4 - fee should be change") assert_equal(Decimal('0.6'), sortedunspent[1]['amount']) assert_false(sortedunspent[1]['change'], "Unspent note valued at 0.6 should not be change") diff --git a/qa/rpc-tests/wallet_doublespend.py b/qa/rpc-tests/wallet_doublespend.py index 37172637844..97c615ec40a 100755 --- a/qa/rpc-tests/wallet_doublespend.py +++ b/qa/rpc-tests/wallet_doublespend.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . import shutil import os.path +from decimal import Decimal from test_framework.mininode import COIN from test_framework.test_framework import BitcoinTestFramework @@ -18,6 +19,7 @@ wait_bitcoinds, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee # Test wallet behaviour with the Orchard protocol class WalletDoubleSpendTest(BitcoinTestFramework): @@ -27,7 +29,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 201), ]] * self.num_nodes) @@ -45,11 +46,12 @@ def run_test_for_recipient_type(self, recipient_type): ua1 = addrRes1['address'] # Create a note matching recipient_type on node 1 - original_zec_amount = 10 - recipients = [{"address": ua1, "amount": original_zec_amount}] - original_amount = original_zec_amount * COIN - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + coinbase_fee = conventional_fee(3) + original_amount = Decimal('10') - coinbase_fee + recipients = [{"address": ua1, "amount": original_amount}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) + acct1_balance = original_amount self.sync_all() self.nodes[0].generate(1) @@ -57,7 +59,7 @@ def run_test_for_recipient_type(self, recipient_type): # Check the value sent to ua1 was received assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount}}, 'minimum_confirmations': 1}, + {'pools': {recipient_type: {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) # Shut down the nodes @@ -75,29 +77,30 @@ def run_test_for_recipient_type(self, recipient_type): # Verify the balance on node 1 assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) # Verify the balance on node 2, on the other side of the split assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct1)) # Spend the note from node 1 - node1_zec_spend_amount = 1 - recipients = [{"address": ua0a, "amount": node1_zec_spend_amount}] - node1_spend_amount = node1_zec_spend_amount * COIN - myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, 0) + fee = conventional_fee(2) + node1_spend_amount = Decimal('1') + recipients = [{"address": ua0a, "amount": node1_spend_amount}] + myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, fee) txa_id = wait_and_assert_operationid_status(self.nodes[1], myopid) + acct1_balance_1 = acct1_balance - node1_spend_amount - fee # Spend the note from node 2 - node2_zec_spend_amount = 2 - recipients = [{"address": ua0b, "amount": node2_zec_spend_amount}] - node2_spend_amount = node2_zec_spend_amount * COIN - myopid = self.nodes[2].z_sendmany(ua1, recipients, 1, 0) + node2_spend_amount = Decimal('2') + recipients = [{"address": ua0b, "amount": node2_spend_amount}] + myopid = self.nodes[2].z_sendmany(ua1, recipients, 1, fee) txb_id = wait_and_assert_operationid_status(self.nodes[2], myopid) + acct1_balance_2 = acct1_balance - node2_spend_amount - fee # Mine the conflicting notes in the split self.sync_all() @@ -105,14 +108,14 @@ def run_test_for_recipient_type(self, recipient_type): self.nodes[3].generate(10) self.sync_all() - # the remaining balance is visible on both sides of the split + # the remaining balance is visible on each side of the split assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount - node1_spend_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance_1 * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount - node2_spend_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance_2 * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct1)) @@ -126,7 +129,7 @@ def run_test_for_recipient_type(self, recipient_type): # acct0a will have received the transaction; it can't see node 2's send assert_equal( - {'pools': {recipient_type: {'valueZat': node1_spend_amount}}, 'minimum_confirmations': 1}, + {'pools': {recipient_type: {'valueZat': node1_spend_amount * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0a)) self.join_network() @@ -141,19 +144,20 @@ def run_test_for_recipient_type(self, recipient_type): # After the reorg, node 2 wins, so its balance is the consensus for # both wallets + acct1_balance = acct1_balance_2 assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount - node2_spend_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) assert_equal( - {'pools': {recipient_type: {'valueZat': original_amount - node2_spend_amount}}, + {'pools': {recipient_type: {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct1)) # acct0b will have received the transaction assert_equal( - {'pools': {recipient_type: {'valueZat': node2_spend_amount}}, + {'pools': {recipient_type: {'valueZat': node2_spend_amount * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0b)) diff --git a/qa/rpc-tests/wallet_isfromme.py b/qa/rpc-tests/wallet_isfromme.py index c38c95be02a..f67948a19c7 100755 --- a/qa/rpc-tests/wallet_isfromme.py +++ b/qa/rpc-tests/wallet_isfromme.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Zcash developers +# Copyright (c) 2021-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -17,6 +17,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -26,7 +27,6 @@ def setup_chain(self): def setup_network(self, split=False): self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(OVERWINTER_BRANCH_ID, 1), nuparams(SAPLING_BRANCH_ID, 1), nuparams(BLOSSOM_BRANCH_ID, 1), @@ -41,46 +41,37 @@ def run_test (self): node = self.nodes[0] node.generate(101) - assert_equal(node.getbalance('', 0), Decimal('6.25')) + assert_equal(Decimal(node.getbalance('', 0)), Decimal('6.25')) coinbase_addr = get_coinbase_address(node) + coinbase_fee = conventional_fee(3) # 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, - 'AllowRevealedSenders', - ), - ) + recipients = [{'address': zaddr, 'amount': Decimal('6.25') - coinbase_fee}] + opid = node.z_sendmany(coinbase_addr, recipients, 0, coinbase_fee, 'AllowRevealedSenders') + wait_and_assert_operationid_status(node, opid) self.sync_all() - assert_equal(node.getbalance('', 0), 0) + assert_equal(Decimal(node.getbalance('', 0)), Decimal('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')) + assert_equal(Decimal(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, - 'AllowRevealedRecipients', - ), - ) + fee = conventional_fee(3) + recipients = [{'address': taddr, 'amount': Decimal('6.25') - coinbase_fee - fee}] + # TODO: this fails for ZIP_317_FEE due to a dust threshold problem: + # "Insufficient funds: have 6.24985, need 0.00000054 more to surpass the dust + # threshold and avoid being forced to over-pay the fee. Alternatively, you could + # specify a fee of 0.0001 to allow overpayment of the conventional fee and have + # this transaction proceed.; note that coinbase outputs will not be selected if + # you specify ANY_TADDR, any transparent recipients are included, or if the + # `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker." + opid = node.z_sendmany(zaddr, recipients, 1, fee, 'AllowRevealedRecipients') + wait_and_assert_operationid_status(node, opid) self.sync_all() # At this point we have created the conditions for the bug in @@ -92,7 +83,7 @@ def run_test (self): 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')) + assert_equal(Decimal(node.getbalance('', 0)), Decimal('12.5') - coinbase_fee - fee) if __name__ == '__main__': WalletIsFromMe().main () diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index aafd0cf26b9..7c4eeb121c1 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -12,8 +12,8 @@ nuparams, start_nodes, wait_and_assert_operationid_status, - LEGACY_DEFAULT_FEE ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -25,7 +25,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 215), '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', @@ -46,10 +45,11 @@ def run_test(self): # 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 - LEGACY_DEFAULT_FEE + fee = conventional_fee(4) + change_amount_2 = receive_amount_1 - receive_amount_2 - fee assert_equal('sapling', self.nodes[0].z_validateaddress(saplingzaddr)['address_type']) recipients = [{"address": saplingzaddr, "amount":receive_amount_2}] - myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedAmounts') + myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, fee, 'AllowRevealedAmounts') txid_2 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -86,9 +86,10 @@ def run_test(self): # 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 - LEGACY_DEFAULT_FEE + fee = conventional_fee(4) + change_amount_3 = change_amount_2 - receive_amount_3 - fee recipients = [{"address": saplingzaddr2, "amount":receive_amount_3}] - myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedAmounts') + myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, fee, 'AllowRevealedAmounts') txid_3 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() unspent_tx = self.nodes[0].z_listunspent(0) @@ -146,9 +147,10 @@ def run_test(self): # Create an Orchard note. account0 = self.nodes[0].z_getnewaccount()['account'] ua0 = self.nodes[0].z_getaddressforaccount(account0)['address'] - receive_amount_4 = Decimal('10.0') + fee = conventional_fee(3) + receive_amount_4 = Decimal('10.0') - fee recipients = [{"address": ua0, "amount": receive_amount_4}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, fee, 'AllowRevealedSenders') txid_4 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index f3b685c5731..2bc06db97d0 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -32,7 +32,6 @@ def __init__(self): def setup_network(self): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 225), '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', @@ -304,7 +303,7 @@ def test_received_orchard(self, height): opid = self.nodes[1].z_sendmany(taddr, [ {'address': uao, 'amount': 1, 'memo': my_memo}, {'address': uaso, 'amount': 2}, - ], 1, 0, 'AllowFullyTransparent') + ], 1, ZIP_317_FEE, 'AllowFullyTransparent') txid0 = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() diff --git a/qa/rpc-tests/wallet_listunspent.py b/qa/rpc-tests/wallet_listunspent.py index c0c2255f9d3..42291ae5362 100755 --- a/qa/rpc-tests/wallet_listunspent.py +++ b/qa/rpc-tests/wallet_listunspent.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2022 The Zcash developers +# Copyright (c) 2016-2024 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.mininode import COIN from test_framework.util import ( assert_equal, get_coinbase_address, @@ -12,6 +13,7 @@ wait_and_assert_operationid_status, NU5_BRANCH_ID ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -21,7 +23,6 @@ def unspent_total(unspent): class WalletListUnspent(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 201), '-allowdeprecated=getnewaddress', ]] * 4) @@ -33,24 +34,23 @@ def run_test(self): def expected_matured_at_height(height): return (height-200)*10 + 250 - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(200)) - assert_equal(self.nodes[1].getbalance(), expected_matured_at_height(200)) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(200)) + assert_equal(Decimal(self.nodes[1].getbalance()), expected_matured_at_height(200)) # Activate NU5 self.nodes[1].generate(1) # height 201 self.sync_all() - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(201)) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(201)) # check balances from before the latest tx - assert_equal(self.nodes[0].getbalance("", 1, False, False, 200), expected_matured_at_height(200)) + assert_equal(Decimal(self.nodes[0].getbalance("", 1, False, False, 200)), expected_matured_at_height(200)) assert_equal(self.matured_at_height(200), expected_matured_at_height(200)) # Shield some coinbase funds so that they become spendable n1acct = self.nodes[1].z_getnewaccount()['account'] n1uaddr = self.nodes[1].z_getaddressforaccount(n1acct)['address'] - opid = self.nodes[0].z_sendmany( - get_coinbase_address(self.nodes[0]), - [{'address': n1uaddr, 'amount': 10}], - 1, 0, 'AllowRevealedSenders') + fee = conventional_fee(3) + recipients = [{'address': n1uaddr, 'amount': Decimal('10') - fee}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], opid) self.sync_all() @@ -60,60 +60,52 @@ def expected_matured_at_height(height): assert_equal( self.nodes[1].z_getbalanceforaccount(n1acct, 1)['pools']['orchard']['valueZat'], - Decimal('1000000000')) + (Decimal('10') - fee) * COIN) # Get a bare legacy transparent address for node 0 n0addr = self.nodes[0].getnewaddress() # Send funds to the node 0 address so we have transparent funds to spend. - opid = self.nodes[1].z_sendmany( - n1uaddr, - [{'address': n0addr, 'amount': 10}], - 1, 0, 'AllowRevealedRecipients') + recipients = [{'address': n0addr, 'amount': Decimal('10') - 2 * fee}] + opid = self.nodes[1].z_sendmany(n1uaddr, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() self.nodes[1].generate(2) self.sync_all() # height 205 - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(205) - 10 + 10) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(205) - 10 + 10 - 2 * fee) # We will then perform several spends, and then check the list of # unspent notes as of various heights. - opid = self.nodes[0].z_sendmany( - 'ANY_TADDR', - [{'address': n1uaddr, 'amount': 2}], - 1, 0, 'AllowFullyTransparent') + recipients = [{'address': n1uaddr, 'amount': Decimal('2')}] + opid = self.nodes[0].z_sendmany('ANY_TADDR', recipients, 1, fee, 'AllowFullyTransparent') wait_and_assert_operationid_status(self.nodes[0], opid) self.nodes[0].generate(2) self.sync_all() # height 207 - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(207) - 10 + 10 - 2) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(207) - 10 + 10 - 2 - 3 * fee) - opid = self.nodes[0].z_sendmany( - 'ANY_TADDR', - [{'address': n1uaddr, 'amount': 3}], - 1, 0, 'AllowFullyTransparent') + recipients = [{'address': n1uaddr, 'amount': Decimal('3')}] + opid = self.nodes[0].z_sendmany('ANY_TADDR', recipients, 1, fee, 'AllowFullyTransparent') wait_and_assert_operationid_status(self.nodes[0], opid) self.nodes[0].generate(2) self.sync_all() # height 209 - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(209) - 10 + 10 - 2 - 3) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(209) - 10 + 10 - 2 - 3 - 4 * fee) - opid = self.nodes[0].z_sendmany( - 'ANY_TADDR', - [{'address': n1uaddr, 'amount': 5}], - 1, 0, 'AllowRevealedSenders') + recipients = [{'address': n1uaddr, 'amount': Decimal('5') - 5 * fee}] + opid = self.nodes[0].z_sendmany('ANY_TADDR', recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], opid) self.nodes[0].generate(2) self.sync_all() # height 211 - assert_equal(self.nodes[0].getbalance(), expected_matured_at_height(211) - 10 + 10 - 2 - 3 - 5) + assert_equal(Decimal(self.nodes[0].getbalance()), expected_matured_at_height(211) - 10 + 10 - 2 - 3 - 5) # check balances at various past points in the chain - assert_equal(self.matured_at_height(205), expected_matured_at_height(205) - 10 + 10) - assert_equal(self.matured_at_height(207), expected_matured_at_height(207) - 10 + 10 - 2) - assert_equal(self.matured_at_height(209), expected_matured_at_height(209) - 10 + 10 - 2 - 3) + assert_equal(self.matured_at_height(205), expected_matured_at_height(205) - 10 + 10 - 2 * fee) + assert_equal(self.matured_at_height(207), expected_matured_at_height(207) - 10 + 10 - 2 - 3 * fee) + assert_equal(self.matured_at_height(209), expected_matured_at_height(209) - 10 + 10 - 2 - 3 - 4 * fee) assert_equal(self.matured_at_height(211), expected_matured_at_height(211) - 10 + 10 - 2 - 3 - 5) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_nullifiers.py b/qa/rpc-tests/wallet_nullifiers.py index 3462517092a..6bc1f832f38 100755 --- a/qa/rpc-tests/wallet_nullifiers.py +++ b/qa/rpc-tests/wallet_nullifiers.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Zcash developers +# Copyright (c) 2016-2024 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, assert_true, bitcoind_processes, \ connect_nodes_bi, start_node, start_nodes, wait_and_assert_operationid_status, \ - get_coinbase_address, LEGACY_DEFAULT_FEE -from test_framework.zip317 import conventional_fee + get_coinbase_address +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -31,12 +31,13 @@ def run_test (self): # send node 0 taddr to zaddr to get out of coinbase # Tests using the default cached chain have one address per coinbase output mytaddr = get_coinbase_address(self.nodes[0]) + coinbase_fee = conventional_fee(3) recipients = [] - recipients.append({"address": myzaddr0, "amount": Decimal('10.0') - LEGACY_DEFAULT_FEE}) # utxo amount less fee + recipients.append({"address": myzaddr0, "amount": Decimal('10.0') - coinbase_fee}) # utxo amount less fee wait_and_assert_operationid_status( self.nodes[0], - self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders'), + self.nodes[0].z_sendmany(mytaddr, recipients, 1, coinbase_fee, 'AllowRevealedSenders'), timeout=120) self.sync_all() @@ -109,7 +110,7 @@ def run_test (self): wait_and_assert_operationid_status( self.nodes[1], - self.nodes[1].z_sendmany(myzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients'), + self.nodes[1].z_sendmany(myzaddr, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients'), timeout=120) self.sync_all() @@ -118,7 +119,7 @@ def run_test (self): # check zaddr balance zsendmany3notevalue = Decimal('1.0') - zaddrremaining2 = zaddrremaining - zsendmany3notevalue - LEGACY_DEFAULT_FEE + zaddrremaining2 = zaddrremaining - zsendmany3notevalue - conventional_fee(3) assert_equal(self.nodes[1].z_getbalance(myzaddr), zaddrremaining2) assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining2) diff --git a/qa/rpc-tests/wallet_orchard.py b/qa/rpc-tests/wallet_orchard.py index 01c27fcd3fb..0d2889e4270 100755 --- a/qa/rpc-tests/wallet_orchard.py +++ b/qa/rpc-tests/wallet_orchard.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 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.mininode import COIN from test_framework.util import ( NU5_BRANCH_ID, assert_equal, @@ -12,6 +13,7 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee from decimal import Decimal @@ -23,7 +25,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 210), ]] * self.num_nodes) @@ -52,9 +53,12 @@ def run_test(self): ua2 = addrRes2['address'] 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') + coinbase_fee = conventional_fee(3) + coinbase_amount = Decimal('10') - coinbase_fee + recipients = [{"address": saplingAddr2, "amount": coinbase_amount}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) + acct2_balance = coinbase_amount # Mine the tx & activate NU5 self.sync_all() @@ -63,14 +67,15 @@ def run_test(self): # Check the value sent to saplingAddr2 was received in node 2's account assert_equal( - {'pools': {'sapling': {'valueZat': Decimal('1000000000')}}, 'minimum_confirmations': 1}, + {'pools': {'sapling': {'valueZat': acct2_balance * COIN}}, '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') + recipients = [{"address": ua1, "amount": coinbase_amount}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) + acct1_balance = coinbase_amount resp = self.nodes[0].getrawtransaction(mytxid, 1)['orchard'] @@ -88,8 +93,8 @@ def run_test(self): flags = resp['flags'] assert_equal(flags['enableSpends'], True) assert_equal(flags['enableOutputs'], True) - assert_equal(resp['valueBalance'], Decimal('-10')) - assert_equal(resp['valueBalanceZat'], Decimal('-1000000000')) + assert_equal(resp['valueBalance'], -coinbase_amount) + assert_equal(resp['valueBalanceZat'], -coinbase_amount * COIN) assert('anchor' in resp) assert('proof' in resp) assert('bindingSig' in resp) @@ -99,16 +104,17 @@ def run_test(self): self.sync_all() assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('1000000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct1_balance * COIN}}, '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') + # Send another coinbase_amount to ua1 + recipients = [{"address": ua1, "amount": coinbase_amount}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) + acct1_balance += coinbase_amount # Mine the tx & generate a majority chain on the 0/1 side of the split self.sync_all() @@ -116,7 +122,7 @@ def run_test(self): self.sync_all() assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('2000000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct1_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) # On the other side of the split, send some funds to node 3 @@ -125,9 +131,12 @@ def run_test(self): assert_equal(acct3, addrRes3['account']) ua3 = addrRes3['address'] + fee = conventional_fee(4) recipients = [{"address": ua3, "amount": Decimal('1')}] - myopid = self.nodes[2].z_sendmany(ua2, recipients, 1, 0, 'AllowRevealedAmounts') + myopid = self.nodes[2].z_sendmany(ua2, recipients, 1, fee, 'AllowRevealedAmounts') rollback_tx = wait_and_assert_operationid_status(self.nodes[2], myopid) + acct3_balance = Decimal('1') + acct2_balance -= Decimal('1') + fee self.sync_all() self.nodes[2].generate(1) @@ -136,11 +145,11 @@ def run_test(self): # 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}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct3_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[3].z_getbalanceforaccount(acct3)) # Check that the mempools are empty @@ -153,7 +162,7 @@ def run_test(self): # 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}, + {'pools': {'orchard': {'valueZat': acct1_balance * COIN}}, '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 @@ -166,9 +175,9 @@ def run_test(self): {'pools': {}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) - # acct2's incoming change (unconfirmed, still in the mempool) is 9 zec + # acct2's incoming change is unconfirmed and still in the mempool assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 0}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 0}, self.nodes[2].z_getbalanceforaccount(acct2, 0)) # The transaction was un-mined, so acct3 should have no confirmed balance @@ -178,7 +187,7 @@ def run_test(self): # acct3's unconfirmed balance is 1 zec assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 0}, + {'pools': {'orchard': {'valueZat': acct3_balance * COIN}}, 'minimum_confirmations': 0}, self.nodes[3].z_getbalanceforaccount(acct3, 0)) # Manually resend the transaction in node 2's mempool @@ -191,41 +200,50 @@ def run_test(self): # The un-mined transaction should now have been re-mined assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct3_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[3].z_getbalanceforaccount(acct3)) # Split the network again self.split_network() # Spend some of acct3's funds on the 2/3 side of the split - recipients = [{"address": ua2, "amount": Decimal('0.5')}] - myopid = self.nodes[3].z_sendmany(ua3, recipients, 1, 0) + fee = conventional_fee(4) + amount = Decimal('0.5') + recipients = [{"address": ua2, "amount": amount}] + myopid = self.nodes[3].z_sendmany(ua3, recipients, 1, fee) rollback_tx = wait_and_assert_operationid_status(self.nodes[3], myopid) + acct2_balance += amount + acct3_balance -= amount + fee self.sync_all() self.nodes[2].generate(1) self.sync_all() assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('950000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) + assert_equal( + {'pools': {'orchard': {'valueZat': acct3_balance * COIN}}, 'minimum_confirmations': 1}, + self.nodes[3].z_getbalanceforaccount(acct3)) + # Generate a majority chain on the 0/1 side of the split, then # re-join the network. self.nodes[1].generate(10) self.join_network() + acct2_balance -= amount # 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[3].getrawmempool())) - # acct2's balance is back to not contain the Orchard->Orchard value + # acct2's balance is back to not containing the Orchard->Orchard value assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) # acct3's sole Orchard note is spent by a transaction in the mempool, so our @@ -236,6 +254,7 @@ def run_test(self): # Manually resend the transaction in node 3's mempool self.nodes[2].resendwallettransactions() + acct2_balance += amount # Sync the network self.sync_all() @@ -244,7 +263,7 @@ def run_test(self): # The un-mined transaction should now have been re-mined assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('950000000')}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': acct2_balance * COIN}}, 'minimum_confirmations': 1}, self.nodes[2].z_getbalanceforaccount(acct2)) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_orchard_change.py b/qa/rpc-tests/wallet_orchard_change.py index fb4487b48ab..a7208c8e132 100755 --- a/qa/rpc-tests/wallet_orchard_change.py +++ b/qa/rpc-tests/wallet_orchard_change.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from decimal import Decimal + from test_framework.test_framework import BitcoinTestFramework +from test_framework.mininode import COIN from test_framework.util import ( NU5_BRANCH_ID, assert_equal, @@ -14,6 +17,7 @@ wait_and_assert_operationid_status, wait_bitcoinds, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE # Test wallet behaviour with the Orchard protocol class WalletOrchardChangeTest(BitcoinTestFramework): @@ -23,7 +27,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 205), '-regtestwalletsetbestchaineveryblock', ]] * self.num_nodes) @@ -46,8 +49,10 @@ def run_test(self): acct0 = self.nodes[0].z_getnewaccount()['account'] ua0 = self.nodes[0].z_getaddressforaccount(acct0, ['sapling', 'orchard'])['address'] - recipients = [{"address": ua0, "amount": 10}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + coinbase_fee = conventional_fee(3) + balance0 = Decimal('10') - coinbase_fee + recipients = [{"address": ua0, "amount": balance0}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) # Mine the tx & activate NU5. @@ -56,7 +61,7 @@ def run_test(self): self.sync_all() assert_equal( - {'pools': {'sapling': {'valueZat': 10_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'sapling': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0), ) @@ -65,8 +70,12 @@ def run_test(self): acct1 = self.nodes[1].z_getnewaccount()['account'] ua1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard'])['address'] - recipients = [{"address": ua1, "amount": 1}] - myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0, 'AllowRevealedAmounts') + recipients = [{"address": ua1, "amount": Decimal('1')}] + # TODO The z_sendmany call fails when passed `None`/`ZIP_317_FEE` because it calculates + # a fee that is too low, so we have to pass in an explicit fee instead. + # https://github.com/zcash/zcash/issues/6956 + fee = conventional_fee(4) + myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, fee, 'AllowRevealedAmounts') source_tx = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -74,8 +83,9 @@ def run_test(self): self.sync_all() # The nodes have the expected split of funds. + balance0 -= Decimal('1') + fee assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0), ) assert_equal( @@ -88,8 +98,8 @@ def run_test(self): 'pool': 'orchard', 'outgoing': False, 'walletInternal': True, - 'value': 9, - 'valueZat': 9_0000_0000, + 'value': balance0, + 'valueZat': balance0 * COIN, }) # Shut down the nodes, and restart so that we can check wallet load @@ -99,7 +109,7 @@ def run_test(self): # The nodes have unaltered balances. assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0), ) assert_equal( @@ -108,15 +118,16 @@ def run_test(self): ) # Send another Orchard transaction from node 0 to node 1. - myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() + balance0 -= Decimal('1') + conventional_fee(2) assert_equal( - {'pools': {'orchard': {'valueZat': 8_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0), ) diff --git a/qa/rpc-tests/wallet_orchard_init.py b/qa/rpc-tests/wallet_orchard_init.py index 75d7746f8c0..f75f668041c 100755 --- a/qa/rpc-tests/wallet_orchard_init.py +++ b/qa/rpc-tests/wallet_orchard_init.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,6 +9,7 @@ from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework +from test_framework.mininode import COIN from test_framework.util import ( NU5_BRANCH_ID, assert_equal, @@ -19,6 +20,7 @@ wait_bitcoinds, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE # Test wallet behaviour with the Orchard protocol class OrchardWalletInitTest(BitcoinTestFramework): @@ -28,7 +30,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 205), '-regtestwalletsetbestchaineveryblock' ]] * self.num_nodes) @@ -50,8 +51,10 @@ def run_test(self): ua1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard'])['address'] # Send a transaction to node 1 so that it has an Orchard note to spend. - recipients = [{"address": ua1, "amount": 10}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + coinbase_fee = conventional_fee(3) + balance1 = Decimal('10') - coinbase_fee + recipients = [{"address": ua1, "amount": balance1}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -60,12 +63,12 @@ def run_test(self): # Check the value sent to ua1 was received assert_equal( - {'pools': {'orchard': {'valueZat': 10_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance1 * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) # Create an Orchard spend, so that the note commitment tree root gets altered. recipients = [{"address": ua0, "amount": 1}] - myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, 0) + myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() @@ -73,8 +76,9 @@ def run_test(self): self.sync_all() # Verify the balance on both nodes + balance1 -= Decimal('1') + conventional_fee(2) assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance1 * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) assert_equal( @@ -103,7 +107,7 @@ def run_test(self): self.setup_network(True) assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance1 * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) # Get a new account with an Orchard UA on node 0 @@ -114,7 +118,7 @@ def run_test(self): # the bug causes the state of note commitment tree in the wallet to not match # the state of the global note commitment tree. recipients = [{"address": ua0new, "amount": 1}] - myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, 0) + myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, ZIP_317_FEE) rollback_tx = wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() @@ -140,21 +144,23 @@ def run_test(self): self.nodes[0].generate(1) self.sync_all() + balance1 -= Decimal('1') + conventional_fee(2) assert_equal( {'pools': {'orchard': {'valueZat': 1_0000_0000}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0new)) # Spend from the note that was just received recipients = [{"address": ua1, "amount": Decimal('0.3')}] - myopid = self.nodes[0].z_sendmany(ua0new, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(ua0new, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() + balance1 += Decimal('0.3') assert_equal( - {'pools': {'orchard': {'valueZat': 8_3000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance1 * COIN}}, 'minimum_confirmations': 1}, self.nodes[1].z_getbalanceforaccount(acct1)) diff --git a/qa/rpc-tests/wallet_orchard_persistence.py b/qa/rpc-tests/wallet_orchard_persistence.py index 99470dccb60..d5ced7f5d4d 100755 --- a/qa/rpc-tests/wallet_orchard_persistence.py +++ b/qa/rpc-tests/wallet_orchard_persistence.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 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.mininode import COIN from test_framework.util import ( NU5_BRANCH_ID, assert_equal, @@ -14,6 +15,7 @@ wait_bitcoinds, wait_and_assert_operationid_status, ) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE from decimal import Decimal @@ -25,7 +27,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 201), ]] * self.num_nodes) @@ -41,8 +42,10 @@ def run_test(self): acct0 = self.nodes[0].z_getnewaccount()['account'] ua0 = self.nodes[0].z_getaddressforaccount(acct0, ['sapling', 'orchard'])['address'] - recipients = [{"address": ua0, "amount": 10}] - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + coinbase_fee = conventional_fee(3) + balance0 = Decimal('10') - coinbase_fee + recipients = [{"address": ua0, "amount": balance0}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) # Mine the tx @@ -51,7 +54,7 @@ def run_test(self): self.sync_all() assert_equal( - {'pools': {'orchard': {'valueZat': 10_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0)) # Send to a new orchard-only unified address @@ -59,15 +62,16 @@ def run_test(self): ua1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard'])['address'] recipients = [{"address": ua1, "amount": 1}] - myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() + balance0 -= Decimal('1') + conventional_fee(2) assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0)) assert_equal( {'pools': {'orchard': {'valueZat': 1_0000_0000}}, 'minimum_confirmations': 1}, @@ -76,7 +80,7 @@ def run_test(self): # Send another Orchard transaction from node 0 back to itself, so that the # note commitment tree gets advanced. recipients = [{"address": ua0, "amount": 1}] - myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -88,20 +92,22 @@ def run_test(self): wait_bitcoinds() self.setup_network() + balance0 -= conventional_fee(2) assert_equal( - {'pools': {'orchard': {'valueZat': 9_0000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0)) recipients = [{"address": ua0, "amount": Decimal('0.5')}] - myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, 0) + myopid = self.nodes[1].z_sendmany(ua1, recipients, 1, ZIP_317_FEE) wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() + balance0 += Decimal('0.5') assert_equal( - {'pools': {'orchard': {'valueZat': 9_5000_0000}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct0)) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_orchard_reindex.py b/qa/rpc-tests/wallet_orchard_reindex.py index 4569957648d..c83a873f562 100755 --- a/qa/rpc-tests/wallet_orchard_reindex.py +++ b/qa/rpc-tests/wallet_orchard_reindex.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2023 The Zcash developers +# Copyright (c) 2023-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -16,12 +16,12 @@ wait_and_assert_operationid_status, wait_bitcoinds, ) +from test_framework.zip317 import conventional_fee from decimal import Decimal import time BASE_ARGS = [ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 210), '-regtestwalletsetbestchaineveryblock', ] @@ -49,10 +49,11 @@ def run_test(self): # Create a transaction with an Orchard output to advance the Orchard # commitment tree. - recipients = [{'address': ua, 'amount': Decimal('10')}] + coinbase_fee = conventional_fee(3) + recipients = [{'address': ua, 'amount': Decimal('10') - coinbase_fee}] myopid = self.nodes[0].z_sendmany( get_coinbase_address(self.nodes[0]), - recipients, 1, 0, 'AllowRevealedSenders') + recipients, 1, coinbase_fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) # Mine the transaction. @@ -62,7 +63,7 @@ def run_test(self): # Confirm that we see the Orchard note in the wallet. assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('10') * COIN}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': (Decimal('10') - coinbase_fee) * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct)) # Mine blocks to ensure that the wallet's tip is far enough beyond NU5 @@ -90,7 +91,7 @@ def run_test(self): # Confirm that we still see the Orchard note in the wallet. assert_equal( - {'pools': {'orchard': {'valueZat': Decimal('10') * COIN}}, 'minimum_confirmations': 1}, + {'pools': {'orchard': {'valueZat': (Decimal('10') - coinbase_fee) * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(acct)) if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index c379bc265e2..8d174b8ed4d 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -7,12 +7,13 @@ from test_framework.util import ( assert_equal, assert_greater_than, + assert_raises_message, connect_nodes_bi, get_coinbase_address, start_nodes, wait_and_assert_operationid_status, - LEGACY_DEFAULT_FEE ) +from test_framework.zip317 import conventional_fee from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -58,6 +59,7 @@ def run_test (self): # Currently at block 195. The next block to be mined 196 is a Sapling block # bci = self.nodes[0].getblockchaininfo() + assert_equal(bci['blocks'], 195) assert_equal(bci['consensus']['chaintip'], '76b809bb') assert_equal(bci['consensus']['nextblock'], '76b809bb') assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') @@ -68,14 +70,14 @@ def run_test (self): self.sync_all() # Node 2 sends the zero-confirmation transparent funds to Node 1 using z_sendmany - recipients = [] - recipients.append({"address":taddr1, "amount": Decimal('0.5')}) - myopid = self.nodes[2].z_sendmany(taddr2, recipients, 0, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent') + fee = conventional_fee(2) + recipients = [{"address": taddr1, "amount": Decimal('0.5')}] + myopid = self.nodes[2].z_sendmany(taddr2, recipients, 0, fee, 'AllowFullyTransparent') txid_zsendmany = wait_and_assert_operationid_status(self.nodes[2], myopid) - # Node 0 shields to Node 2, a coinbase utxo of value 10.0 less default fee - zsendamount = Decimal('10.0') - LEGACY_DEFAULT_FEE - result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr2, LEGACY_DEFAULT_FEE, 1) + # Node 0 shields to Node 2, a coinbase utxo of value 10.0 less fee + shield_fee = conventional_fee(3) + result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr2, shield_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 @@ -86,8 +88,8 @@ def run_test (self): # Verify balance assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('0.5')) - assert_equal(self.nodes[2].getbalance(), Decimal('0.5') - LEGACY_DEFAULT_FEE) - assert_equal(self.nodes[2].z_getbalance(zaddr2), zsendamount) + assert_equal(self.nodes[2].getbalance(), Decimal('0.5') - fee) + assert_equal(self.nodes[2].z_getbalance(zaddr2), Decimal('10.0') - shield_fee) # Verify transaction version is 4 (intended for Sapling+) result = self.nodes[0].getrawtransaction(txid_transparent, 1) @@ -104,32 +106,20 @@ def run_test (self): # Currently at block 199. The next block to be mined 200 is a Blossom block # bci = self.nodes[0].getblockchaininfo() + assert_equal(bci['blocks'], 199) assert_equal(bci['consensus']['chaintip'], '76b809bb') assert_equal(bci['consensus']['nextblock'], '2bb40e60') assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') # Test using expiryheight parameter of createrawtransaction when Blossom is active in the next block - errorString = "" - try: - self.nodes[0].createrawtransaction([], {}, 0, 499999999) - except JSONRPCException as e: - errorString = e.error['message'] - assert_equal("", errorString) - try: - self.nodes[0].createrawtransaction([], {}, 0, -1) - except JSONRPCException as e: - errorString = e.error['message'] - assert_equal("Invalid parameter, expiryheight must be nonnegative and less than 500000000" in errorString, True) - try: - self.nodes[0].createrawtransaction([], {}, 0, 500000000) - except JSONRPCException as e: - errorString = e.error['message'] - assert_equal("Invalid parameter, expiryheight must be nonnegative and less than 500000000" in errorString, True) - try: - self.nodes[0].createrawtransaction([], {}, 0, 200) - except JSONRPCException as e: - errorString = e.error['message'] - assert_equal("Invalid parameter, expiryheight should be at least 203 to avoid transaction expiring soon" in errorString, True) + assert_equal(type(self.nodes[0].createrawtransaction([], {}, 0, 499999999)), str) + + assert_raises_message(JSONRPCException, "Invalid parameter, expiryheight must be nonnegative and less than 500000000", + self.nodes[0].createrawtransaction, [], {}, 0, -1) + assert_raises_message(JSONRPCException, "Invalid parameter, expiryheight must be nonnegative and less than 500000000", + self.nodes[0].createrawtransaction, [], {}, 0, 500000000) + assert_raises_message(JSONRPCException, "Invalid parameter, expiryheight should be at least 203 to avoid transaction expiring soon", + self.nodes[0].createrawtransaction, [], {}, 0, 200) # Node 0 sends transparent funds to Node 3 tsendamount = Decimal('1.0') @@ -137,14 +127,12 @@ def run_test (self): self.sync_all() # Node 3 sends the zero-confirmation transparent funds to Node 1 using z_sendmany - recipients = [] - recipients.append({"address":taddr1, "amount": Decimal('0.5')}) - myopid = self.nodes[3].z_sendmany(taddr3, recipients, 0, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent') + recipients = [{"address": taddr1, "amount": Decimal('0.5')}] + myopid = self.nodes[3].z_sendmany(taddr3, recipients, 0, fee, 'AllowFullyTransparent') txid_zsendmany = wait_and_assert_operationid_status(self.nodes[3], myopid) - # Node 0 shields to Node 3, a coinbase utxo of value 10.0 less default fee - zsendamount = Decimal('10.0') - LEGACY_DEFAULT_FEE - result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr3, LEGACY_DEFAULT_FEE, 1) + # Node 0 shields to Node 3, a coinbase utxo of value 10.0 less fee + result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr3, shield_fee, 1) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], result['opid']) # Mine the first Blossom block @@ -156,16 +144,17 @@ def run_test (self): # size_on_disk should be > 0 assert_greater_than(bci['size_on_disk'], 0) + assert_equal(bci['blocks'], 200) assert_equal(bci['consensus']['chaintip'], '2bb40e60') assert_equal(bci['consensus']['nextblock'], '2bb40e60') assert_equal(bci['upgrades']['2bb40e60']['status'], 'active') # Verify balance assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('1.0')) - assert_equal(self.nodes[3].getbalance(), Decimal('0.5') - LEGACY_DEFAULT_FEE) - assert_equal(self.nodes[3].z_getbalance(zaddr3), zsendamount) + assert_equal(self.nodes[3].getbalance(), Decimal('0.5') - fee) + assert_equal(self.nodes[3].z_getbalance(zaddr3), Decimal('10.0') - shield_fee) - # Verify transaction version is 4 (intended for Sapling+) + # Verify transaction version is 4 (Sapling onward) result = self.nodes[0].getrawtransaction(txid_transparent, 1) assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) diff --git a/qa/rpc-tests/wallet_persistence.py b/qa/rpc-tests/wallet_persistence.py index 74085e6b069..a9774880bd1 100755 --- a/qa/rpc-tests/wallet_persistence.py +++ b/qa/rpc-tests/wallet_persistence.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -12,6 +12,8 @@ initialize_chain_clean, connect_nodes_bi, wait_bitcoinds, wait_and_assert_operationid_status ) +from test_framework.zip317 import conventional_fee + from decimal import Decimal class WalletPersistenceTest (BitcoinTestFramework): @@ -22,7 +24,6 @@ def setup_chain(self): def setup_network(self, split=False): self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', '-allowdeprecated=z_gettotalbalance', @@ -95,9 +96,9 @@ def check_chain_value(pool, expected_id, expected_value): # Node 0 shields funds to Sapling address taddr0 = get_coinbase_address(self.nodes[0]) - recipients = [] - recipients.append({"address": sapling_addr, "amount": Decimal('20')}) - myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0, 'AllowRevealedSenders') + fee = conventional_fee(4) + recipients = [{"address": sapling_addr, "amount": Decimal('20') - fee}] + myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -106,15 +107,15 @@ def check_chain_value(pool, expected_id, expected_value): self.sync_all() # Verify shielded balance - assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('20')) + assert_equal(Decimal(self.nodes[0].z_getbalance(sapling_addr)), Decimal('20') - fee) # Verify size of pools chainInfo = self.nodes[0].getblockchaininfo() pools = chainInfo['valuePools'] check_chain_value(chainInfo['chainSupply'], None, expected_supply) # Supply - check_chain_value(pools[0], 'transparent', expected_supply - Decimal('20')) # Transparent + check_chain_value(pools[0], 'transparent', expected_supply - (Decimal('20') - fee)) # Transparent check_chain_value(pools[1], 'sprout', Decimal('0')) - check_chain_value(pools[2], 'sapling', Decimal('20')) + check_chain_value(pools[2], 'sapling', Decimal('20') - fee) check_chain_value(pools[3], 'orchard', Decimal('0')) # Restart the nodes @@ -126,16 +127,15 @@ def check_chain_value(pool, expected_id, expected_value): chainInfo = self.nodes[0].getblockchaininfo() pools = chainInfo['valuePools'] check_chain_value(chainInfo['chainSupply'], None, expected_supply) # Supply - check_chain_value(pools[0], 'transparent', expected_supply - Decimal('20')) # Transparent + check_chain_value(pools[0], 'transparent', expected_supply - (Decimal('20') - fee)) # Transparent check_chain_value(pools[1], 'sprout', Decimal('0')) - check_chain_value(pools[2], 'sapling', Decimal('20')) + check_chain_value(pools[2], 'sapling', Decimal('20') - fee) check_chain_value(pools[3], 'orchard', Decimal('0')) # Node 0 sends some shielded funds to Node 1 dest_addr = self.nodes[1].z_getnewaddress('sapling') - recipients = [] - recipients.append({"address": dest_addr, "amount": Decimal('15')}) - myopid = self.nodes[0].z_sendmany(sapling_addr, recipients, 1, 0) + recipients = [{"address": dest_addr, "amount": Decimal('15') - fee}] + myopid = self.nodes[0].z_sendmany(sapling_addr, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -143,8 +143,8 @@ def check_chain_value(pool, expected_id, expected_value): self.sync_all() # Verify balances - assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('5')) - assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('15')) + assert_equal(Decimal(self.nodes[0].z_getbalance(sapling_addr)), Decimal('5') - fee) + assert_equal(Decimal(self.nodes[1].z_getbalance(dest_addr)), Decimal('15') - fee) # Restart the nodes stop_nodes(self.nodes) @@ -152,20 +152,20 @@ def check_chain_value(pool, expected_id, expected_value): self.setup_network() # Verify balances - assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('5')) - assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('15')) + assert_equal(Decimal(self.nodes[0].z_getbalance(sapling_addr)), Decimal('5') - fee) + assert_equal(Decimal(self.nodes[1].z_getbalance(dest_addr)), Decimal('15') - fee) # Verify importing a spending key will update and persist the nullifiers and witnesses correctly sk0 = self.nodes[0].z_exportkey(sapling_addr) self.nodes[2].z_importkey(sk0, "yes") - assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('5')) + assert_equal(Decimal(self.nodes[2].z_getbalance(sapling_addr)), Decimal('5') - fee) # Verify importing a viewing key will update and persist the nullifiers and witnesses correctly extfvk0 = self.nodes[0].z_exportviewingkey(sapling_addr) self.nodes[3].z_importviewingkey(extfvk0, "yes") - assert_equal(self.nodes[3].z_getbalance(sapling_addr), Decimal('5')) - assert_equal(self.nodes[3].z_gettotalbalance()['private'], '0.00') - assert_equal(self.nodes[3].z_gettotalbalance(1, True)['private'], '5.00') + assert_equal(Decimal(self.nodes[3].z_getbalance(sapling_addr)), Decimal('5') - fee) + assert_equal(Decimal(self.nodes[3].z_gettotalbalance()['private']), Decimal('0')) + assert_equal(Decimal(self.nodes[3].z_gettotalbalance(1, True)['private']), Decimal('5') - fee) # Restart the nodes stop_nodes(self.nodes) @@ -175,15 +175,14 @@ def check_chain_value(pool, expected_id, expected_value): # Verify nullifiers persisted correctly by checking balance # Prior to PR #3590, there will be an error as spent notes are considered unspent: # Assertion failed: expected: <25.00000000> but was: <5> - assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('5')) - assert_equal(self.nodes[3].z_getbalance(sapling_addr), Decimal('5')) - assert_equal(self.nodes[3].z_gettotalbalance()['private'], '0.00') - assert_equal(self.nodes[3].z_gettotalbalance(1, True)['private'], '5.00') + assert_equal(Decimal(self.nodes[2].z_getbalance(sapling_addr)), Decimal('5') - fee) + assert_equal(Decimal(self.nodes[3].z_getbalance(sapling_addr)), Decimal('5') - fee) + assert_equal(Decimal(self.nodes[3].z_gettotalbalance()['private']), Decimal('0')) + assert_equal(Decimal(self.nodes[3].z_gettotalbalance(1, True)['private']), Decimal('5') - fee) # Verity witnesses persisted correctly by sending shielded funds - recipients = [] - recipients.append({"address": dest_addr, "amount": Decimal('1')}) - myopid = self.nodes[2].z_sendmany(sapling_addr, recipients, 1, 0) + recipients = [{"address": dest_addr, "amount": Decimal('1')}] + myopid = self.nodes[2].z_sendmany(sapling_addr, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[2], myopid) self.sync_all() @@ -191,8 +190,8 @@ def check_chain_value(pool, expected_id, expected_value): self.sync_all() # Verify balances - assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('4')) - assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('16')) + assert_equal(Decimal(self.nodes[2].z_getbalance(sapling_addr)), Decimal('4') - 2*fee) + assert_equal(Decimal(self.nodes[1].z_getbalance(dest_addr)), Decimal('16') - fee) if __name__ == '__main__': WalletPersistenceTest().main() diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index 609a35437bd..9bf15502b14 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,8 +9,8 @@ get_coinbase_address, start_nodes, wait_and_assert_operationid_status, - LEGACY_DEFAULT_FEE ) +from test_framework.zip317 import ZIP_317_FEE, conventional_fee from decimal import Decimal @@ -19,7 +19,6 @@ class WalletSaplingTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', @@ -42,21 +41,21 @@ def run_test(self): assert_equal(self.nodes[0].z_validateaddress(saplingAddr1)['address_type'], 'sapling') # Verify balance - assert_equal(self.nodes[0].z_getbalance(saplingAddr0), Decimal('0')) - assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal('0')) - assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('0')) + assert_equal(Decimal(self.nodes[0].z_getbalance(saplingAddr0)), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_getbalance(saplingAddr1)), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_getbalance(taddr1)), Decimal('0')) # Node 0 shields some funds # taddr -> Sapling - recipients = [] - recipients.append({"address": saplingAddr0, "amount": Decimal('10')}) - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + coinbase_fee = conventional_fee(3) + recipients = [{"address": saplingAddr0, "amount": Decimal('10') - coinbase_fee}] + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() # Shield another coinbase UTXO - myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders') + myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -64,16 +63,17 @@ def run_test(self): self.sync_all() # Verify balance - assert_equal(self.nodes[0].z_getbalance(saplingAddr0), Decimal('20')) - assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal('0')) - assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('0')) + balance0 = Decimal('20') - 2 * coinbase_fee + assert_equal(Decimal(self.nodes[0].z_getbalance(saplingAddr0)), balance0) + assert_equal(Decimal(self.nodes[1].z_getbalance(saplingAddr1)), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_getbalance(taddr1)), Decimal('0')) # Node 0 sends some shielded funds to node 1 # Sapling -> Sapling # -> Sapling (change) recipients = [] recipients.append({"address": saplingAddr1, "amount": Decimal('15')}) - myopid = self.nodes[0].z_sendmany(saplingAddr0, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(saplingAddr0, recipients, 1, ZIP_317_FEE) mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -81,9 +81,11 @@ def run_test(self): self.sync_all() # Verify balance - assert_equal(self.nodes[0].z_getbalance(saplingAddr0), Decimal('5')) - assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal('15')) - assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('0')) + balance1 = Decimal('15') + balance0 -= balance1 + conventional_fee(2) + assert_equal(Decimal(self.nodes[0].z_getbalance(saplingAddr0)), balance0) + assert_equal(Decimal(self.nodes[1].z_getbalance(saplingAddr1)), balance1) + assert_equal(Decimal(self.nodes[1].z_getbalance(taddr1)), Decimal('0')) # Node 1 sends some shielded funds to node 0, as well as unshielding # Sapling -> Sapling @@ -92,7 +94,7 @@ def run_test(self): recipients = [] recipients.append({"address": saplingAddr0, "amount": Decimal('5')}) recipients.append({"address": taddr1, "amount": Decimal('5')}) - myopid = self.nodes[1].z_sendmany(saplingAddr1, recipients, 1, 0, 'AllowRevealedRecipients') + myopid = self.nodes[1].z_sendmany(saplingAddr1, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') mytxid = wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() @@ -100,13 +102,16 @@ def run_test(self): self.sync_all() # Verify balance - assert_equal(self.nodes[0].z_getbalance(saplingAddr0), Decimal('10')) - assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal('5')) - assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('5')) - - # Verify existence of Sapling related JSON fields + fee = conventional_fee(3) + balance0 += Decimal('5') + balance1 -= Decimal('10') + fee + assert_equal(Decimal(self.nodes[0].z_getbalance(saplingAddr0)), balance0) + assert_equal(Decimal(self.nodes[1].z_getbalance(saplingAddr1)), balance1) + assert_equal(Decimal(self.nodes[1].z_getbalance(taddr1)), Decimal('5')) + + # Verify existence of Sapling-related JSON fields resp = self.nodes[0].getrawtransaction(mytxid, 1) - assert_equal(resp['valueBalance'], Decimal('5')) + assert_equal(resp['valueBalance'], Decimal('5') + fee) assert(len(resp['vShieldedSpend']) == 1) assert(len(resp['vShieldedOutput']) == 2) assert('bindingSig' in resp) @@ -130,37 +135,38 @@ def run_test(self): saplingAddrInfo0 = self.nodes[2].z_importkey(sk0, "yes") assert_equal(saplingAddrInfo0["address_type"], "sapling") assert_equal(saplingAddrInfo0["address"], saplingAddr0) - assert_equal(self.nodes[2].z_getbalance(saplingAddrInfo0["address"]), Decimal('10')) + assert_equal(Decimal(self.nodes[2].z_getbalance(saplingAddrInfo0["address"])), balance0) sk1 = self.nodes[1].z_exportkey(saplingAddr1) saplingAddrInfo1 = self.nodes[2].z_importkey(sk1, "yes") assert_equal(saplingAddrInfo1["address_type"], "sapling") assert_equal(saplingAddrInfo1["address"], saplingAddr1) - assert_equal(self.nodes[2].z_getbalance(saplingAddrInfo1["address"]), Decimal('5')) + assert_equal(Decimal(self.nodes[2].z_getbalance(saplingAddrInfo1["address"])), balance1) # Verify importing a viewing key will update the nullifiers and witnesses correctly extfvk0 = self.nodes[0].z_exportviewingkey(saplingAddr0) saplingAddrInfo0 = self.nodes[3].z_importviewingkey(extfvk0, "yes") assert_equal(saplingAddrInfo0["address_type"], "sapling") assert_equal(saplingAddrInfo0["address"], saplingAddr0) - assert_equal(self.nodes[3].z_getbalance(saplingAddrInfo0["address"]), Decimal('10')) + assert_equal(Decimal(self.nodes[3].z_getbalance(saplingAddrInfo0["address"])), balance0) extfvk1 = self.nodes[1].z_exportviewingkey(saplingAddr1) saplingAddrInfo1 = self.nodes[3].z_importviewingkey(extfvk1, "yes") assert_equal(saplingAddrInfo1["address_type"], "sapling") assert_equal(saplingAddrInfo1["address"], saplingAddr1) - assert_equal(self.nodes[3].z_getbalance(saplingAddrInfo1["address"]), Decimal('5')) + assert_equal(Decimal(self.nodes[3].z_getbalance(saplingAddrInfo1["address"])), balance1) # Verify that z_gettotalbalance only includes watch-only addresses when requested - assert_equal(self.nodes[3].z_gettotalbalance()['private'], '0.00') - assert_equal(self.nodes[3].z_gettotalbalance(1, True)['private'], '15.00') + assert_equal(Decimal(self.nodes[3].z_gettotalbalance()['private']), Decimal('0.00')) + assert_equal(Decimal(self.nodes[3].z_gettotalbalance(1, True)['private']), balance0 + balance1) # Make sure we get a useful error when trying to send to both sprout and sapling node4_sproutaddr = self.nodes[3].z_getnewaddress('sprout') node4_saplingaddr = self.nodes[3].z_getnewaddress('sapling') + fee = conventional_fee(5) myopid = self.nodes[1].z_sendmany( taddr1, [{'address': node4_sproutaddr, 'amount': Decimal('2.5')}, - {'address': node4_saplingaddr, 'amount': Decimal('2.5') - LEGACY_DEFAULT_FEE}], - 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders' + {'address': node4_saplingaddr, 'amount': Decimal('2.5') - fee}], + 1, fee, 'AllowRevealedSenders' ) wait_and_assert_operationid_status(self.nodes[1], myopid, "failed", "Sending funds into the Sprout pool is no longer supported.") diff --git a/qa/rpc-tests/wallet_sendmany_any_taddr.py b/qa/rpc-tests/wallet_sendmany_any_taddr.py index 61e2ee26104..5ff8b7381a6 100755 --- a/qa/rpc-tests/wallet_sendmany_any_taddr.py +++ b/qa/rpc-tests/wallet_sendmany_any_taddr.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) 2020 The Zcash developers +# Copyright (c) 2020-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . +from decimal import Decimal + from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - LEGACY_DEFAULT_FEE, assert_equal, assert_raises_message, connect_nodes_bi, @@ -13,7 +14,7 @@ sync_blocks, wait_and_assert_operationid_status, ) -from test_framework.zip317 import ZIP_317_FEE +from test_framework.zip317 import conventional_fee, ZIP_317_FEE TX_EXPIRY_DELTA = 10 TX_EXPIRING_SOON_THRESHOLD = 3 @@ -22,7 +23,6 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-txexpirydelta=%d' % TX_EXPIRY_DELTA, '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', @@ -43,44 +43,42 @@ def run_test(self): node3taddr2 = self.nodes[3].getnewaddress() # Prepare some non-coinbase UTXOs + fee = conventional_fee(27) wait_and_assert_operationid_status( self.nodes[3], - self.nodes[3].z_shieldcoinbase("*", node3zaddr, 0, None, None, 'AllowLinkingAccountAddresses')['opid'], + self.nodes[3].z_shieldcoinbase("*", node3zaddr, fee, None, None, 'AllowLinkingAccountAddresses')['opid'], ) self.sync_all() self.nodes[0].generate(1) self.sync_all() - assert_equal(self.nodes[3].z_getbalance(node3zaddr), 250) + assert_equal(Decimal(self.nodes[3].z_getbalance(node3zaddr)), Decimal('250') - fee) wait_and_assert_operationid_status( self.nodes[3], self.nodes[3].z_sendmany( node3zaddr, [ - {'address': node3taddr1, 'amount': 60}, - {'address': node3taddr2, 'amount': 75}, + {'address': node3taddr1, 'amount': Decimal('60')}, + {'address': node3taddr2, 'amount': Decimal('75')}, ], - 1, - LEGACY_DEFAULT_FEE, - 'AllowRevealedRecipients', - ), + 1, ZIP_317_FEE, 'AllowRevealedRecipients'), ) self.sync_all() self.nodes[0].generate(1) self.sync_all() # Check the various balances. - assert_equal(self.nodes[1].z_getbalance(recipient), 0) - assert_equal(self.nodes[3].z_getbalance(node3taddr1), 60) - assert_equal(self.nodes[3].z_getbalance(node3taddr2), 75) + assert_equal(Decimal(self.nodes[1].z_getbalance(recipient)), Decimal('0')) + assert_equal(Decimal(self.nodes[3].z_getbalance(node3taddr1)), Decimal('60')) + assert_equal(Decimal(self.nodes[3].z_getbalance(node3taddr2)), Decimal('75')) # We should be able to spend multiple UTXOs at once wait_and_assert_operationid_status( self.nodes[3], self.nodes[3].z_sendmany( 'ANY_TADDR', - [{'address': recipient, 'amount': 100}], - 1, LEGACY_DEFAULT_FEE, 'NoPrivacy'), + [{'address': recipient, 'amount': Decimal('100')}], + 1, ZIP_317_FEE, 'NoPrivacy'), ) self.sync_all() @@ -88,19 +86,20 @@ def run_test(self): self.sync_all() # The recipient has their funds! - assert_equal(self.nodes[1].z_getbalance(recipient), 100) + assert_equal(Decimal(self.nodes[1].z_getbalance(recipient)), Decimal('100')) # Change is sent to a new t-address. - assert_equal(self.nodes[3].z_getbalance(node3taddr1), 0) - assert_equal(self.nodes[3].z_getbalance(node3taddr2), 0) + assert_equal(Decimal(self.nodes[3].z_getbalance(node3taddr1)), Decimal('0')) + assert_equal(Decimal(self.nodes[3].z_getbalance(node3taddr2)), Decimal('0')) # Send from a change t-address. + fee = conventional_fee(3) wait_and_assert_operationid_status( self.nodes[3], self.nodes[3].z_sendmany( 'ANY_TADDR', - [{'address': recipient, 'amount': 20}], - 1, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent'), + [{'address': recipient, 'amount': Decimal('20')}], + 1, fee, 'AllowFullyTransparent'), ) self.sync_all() @@ -108,18 +107,23 @@ def run_test(self): self.sync_all() # The recipient has their funds! - assert_equal(self.nodes[1].z_getbalance(recipient), 120) + assert_equal(Decimal(self.nodes[1].z_getbalance(recipient)), Decimal('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}], - 1, LEGACY_DEFAULT_FEE, 'AllowLinkingAccountAddresses') - wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds: have 14.99998, need 20.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") + [{'address': recipient, 'amount': Decimal('20') - fee}], + 1, fee, 'AllowLinkingAccountAddresses') + wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds: have 14.99965, need 20.00; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") - # Create an expired transaction on node 3. + # Create a transaction that will expire on node 3. self.split_network() - expire_transparent = self.nodes[3].sendtoaddress(node2taddr1, 14) + myopid = self.nodes[3].z_sendmany( + 'ANY_TADDR', + [{'address': node2taddr1, 'amount': Decimal('14')}], + 1, ZIP_317_FEE, 'AllowFullyTransparent') + + expire_transparent = wait_and_assert_operationid_status(self.nodes[3], myopid) assert(expire_transparent in self.nodes[3].getrawmempool()) self.sync_all() assert_equal('waiting', self.nodes[2].gettransaction(expire_transparent)['status']) @@ -133,26 +137,27 @@ def run_test(self): # 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() - assert_raises_message(AssertionError, "tx unpaid action limit exceeded", + assert_raises_message(AssertionError, "tx unpaid action limit exceeded: 50 action(s) exceeds limit of 0", wait_and_assert_operationid_status, self.nodes[2], - self.nodes[2].z_shieldcoinbase("*", node2zaddr, 0, None, None, 'AllowLinkingAccountAddresses')['opid'], + self.nodes[2].z_shieldcoinbase("*", node2zaddr, conventional_fee(2), None, None, 'AllowLinkingAccountAddresses')['opid'], ) wait_and_assert_operationid_status( self.nodes[2], self.nodes[2].z_shieldcoinbase("*", node2zaddr, ZIP_317_FEE, None, None, 'AllowLinkingAccountAddresses')['opid'], ) self.sync_all() - assert_equal(0, self.nodes[2].getbalance()) + assert_equal(Decimal('0'), Decimal(self.nodes[2].getbalance())) # Check that ANY_TADDR doesn't select an expired output. + fee = conventional_fee(3) wait_and_assert_operationid_status( self.nodes[2], self.nodes[2].z_sendmany( 'ANY_TADDR', - [{'address': recipient, 'amount': 13}], - 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders'), - "failed", "Insufficient funds: have 0.00, need 13.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker. (This transaction may require selecting transparent coins that were sent to multiple addresses, which is not enabled by default because it would create a public link between those 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.)") + [{'address': recipient, 'amount': Decimal('13') - fee}], + 1, fee, 'AllowRevealedSenders'), + "failed", "Insufficient funds: have 0.00, need 13.00; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker. (This transaction may require selecting transparent coins that were sent to multiple addresses, which is not enabled by default because it would create a public link between those 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.)") if __name__ == '__main__': WalletSendManyAnyTaddr().main() diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py index 1718a5cf0d2..e58fc623e91 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase.py +++ b/qa/rpc-tests/wallet_shieldcoinbase.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017 The Zcash developers +# Copyright (c) 2017-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -20,7 +20,6 @@ def setup_chain(self): def setup_network(self, split=False): args = [ - '-minrelaytxfee=0', '-regtestprotectcoinbase', '-debug=zrpcunsafe', nuparams(NU5_BRANCH_ID, self.nu5_activation), @@ -45,8 +44,8 @@ def run_test (self): self.nodes[0].generate(4) self.sync_all() walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 50) - assert_equal(walletinfo['balance'], 0) + assert_equal(Decimal(walletinfo['immature_balance']), Decimal('50')) + assert_equal(Decimal(walletinfo['balance']), Decimal('0')) self.sync_all() self.nodes[2].generate(1) self.nodes[2].generate(1) @@ -54,9 +53,9 @@ def run_test (self): self.sync_all() self.nodes[1].generate(101) self.sync_all() - assert_equal(self.nodes[0].getbalance(), 50) - assert_equal(self.nodes[1].getbalance(), 10) - assert_equal(self.nodes[2].getbalance(), 30) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('50')) + assert_equal(Decimal(self.nodes[1].getbalance()), Decimal('10')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('30')) # create one zaddr that is the target of all shielding myzaddr = self.test_init_zaddr(self.nodes[0]) @@ -102,31 +101,33 @@ def run_test (self): errorString = e.error['message'] assert_equal("JSON integer out of range" in errorString, True) - # Shield coinbase utxos from node 0 of value 40, standard fee - result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr) + # Shield coinbase utxos from node 0 of value 40 + fee = conventional_fee(6) + result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, fee) wait_and_assert_operationid_status(self.nodes[0], result['opid']) self.sync_all() self.nodes[1].generate(1) self.sync_all() # 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')) - self.test_check_balance_zaddr(self.nodes[0], Decimal('40.0') - conventional_fee(6)) - assert_equal(self.nodes[1].getbalance(), 20) - assert_equal(self.nodes[2].getbalance(), 30) - - # Shield coinbase utxos from any node 2 taddr, and set fee to 0 - result = self.nodes[2].z_shieldcoinbase("*", myzaddr, 0, None, None, 'AllowLinkingAccountAddresses') + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('10')) + assert_equal(Decimal(self.nodes[0].z_getbalance(do_not_shield_taddr)), Decimal('10')) + self.test_check_balance_zaddr(self.nodes[0], Decimal('40') - fee) + assert_equal(Decimal(self.nodes[1].getbalance()), Decimal('20')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('30')) + + # Shield coinbase utxos from any node 2 taddr + fee2 = conventional_fee(5) + result = self.nodes[2].z_shieldcoinbase("*", myzaddr, fee2, None, None, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(self.nodes[2], result['opid']) self.sync_all() self.nodes[1].generate(1) self.sync_all() - assert_equal(self.nodes[0].getbalance(), 10) - self.test_check_balance_zaddr(self.nodes[0], Decimal('70.0') - conventional_fee(6)) - assert_equal(self.nodes[1].getbalance(), 30) - assert_equal(self.nodes[2].getbalance(), 0) + assert_equal(Decimal(self.nodes[0].getbalance()), Decimal('10')) + self.test_check_balance_zaddr(self.nodes[0], Decimal('70') - fee - fee2) + assert_equal(Decimal(self.nodes[1].getbalance()), Decimal('30')) + assert_equal(Decimal(self.nodes[2].getbalance()), Decimal('0')) # Generate 800 coinbase utxos on node 0, and 20 coinbase utxos on node 2 self.nodes[0].generate(800) @@ -139,17 +140,17 @@ def run_test (self): def verify_locking(first, second, limit): result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, ZIP_317_FEE, limit) - assert_equal(result["shieldingUTXOs"], Decimal(first)) - assert_equal(result["remainingUTXOs"], Decimal(second)) + assert_equal(Decimal(result["shieldingUTXOs"]), Decimal(first)) + assert_equal(Decimal(result["remainingUTXOs"]), Decimal(second)) remainingValue = result["remainingValue"] opid1 = result['opid'] # Verify that utxos are locked (not available for selection) by queuing up another shielding operation result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, ZIP_317_FEE, 0) - assert_equal(result["shieldingValue"], Decimal(remainingValue)) - assert_equal(result["shieldingUTXOs"], Decimal(second)) - assert_equal(result["remainingValue"], Decimal('0')) - assert_equal(result["remainingUTXOs"], Decimal('0')) + assert_equal(Decimal(result["shieldingValue"]), Decimal(remainingValue)) + assert_equal(Decimal(result["shieldingUTXOs"]), Decimal(second)) + assert_equal(Decimal(result["remainingValue"]), Decimal('0')) + assert_equal(Decimal(result["remainingUTXOs"]), Decimal('0')) opid2 = result['opid'] # wait for both async operations to complete @@ -172,14 +173,14 @@ def verify_locking(first, second, limit): self.sync_all() mytaddr = get_coinbase_address(self.nodes[0], 100) result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, ZIP_317_FEE, None, 'DEADBEEF') - assert_equal(result["shieldingUTXOs"], Decimal('50')) - assert_equal(result["remainingUTXOs"], Decimal('50')) + assert_equal(Decimal(result["shieldingUTXOs"]), Decimal('50')) + assert_equal(Decimal(result["remainingUTXOs"]), Decimal('50')) wait_and_assert_operationid_status(self.nodes[0], result['opid']) # Verify maximum number of utxos which node 0 can shield can be set by the limit parameter result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, ZIP_317_FEE, 33, None) - assert_equal(result["shieldingUTXOs"], Decimal('33')) - assert_equal(result["remainingUTXOs"], Decimal('17')) + assert_equal(Decimal(result["shieldingUTXOs"]), Decimal('33')) + assert_equal(Decimal(result["remainingUTXOs"]), Decimal('17')) wait_and_assert_operationid_status(self.nodes[0], result['opid']) # Don't sync node 2 which rejects the tx due to its mempooltxinputlimit sync_blocks(self.nodes[:2]) diff --git a/qa/rpc-tests/wallet_shieldingcoinbase.py b/qa/rpc-tests/wallet_shieldingcoinbase.py index 49733966904..a8ad203b63e 100755 --- a/qa/rpc-tests/wallet_shieldingcoinbase.py +++ b/qa/rpc-tests/wallet_shieldingcoinbase.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Zcash developers +# Copyright (c) 2016-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -9,7 +9,7 @@ from test_framework.util import assert_equal, initialize_chain_clean, \ start_nodes, connect_nodes_bi, wait_and_assert_operationid_status, \ wait_and_assert_operationid_status_result, get_coinbase_address, \ - check_node_log, LEGACY_DEFAULT_FEE + check_node_log from test_framework.zip317 import conventional_fee, WEIGHT_RATIO_CAP, ZIP_317_FEE import sys @@ -36,7 +36,6 @@ def setup_chain(self): # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-regtestshieldcoinbase', '-debug=zrpcunsafe', '-allowdeprecated=getnewaddress', @@ -91,7 +90,7 @@ def run_test (self): # Node 3 will test that watch only address utxos are not selected self.nodes[3].importaddress(mytaddr) - recipients= [{"address":myzaddr, "amount": Decimal('1')}] + recipients= [{"address": myzaddr, "amount": Decimal('1')}] try: myopid = self.nodes[3].z_sendmany(mytaddr, recipients) except JSONRPCException as e: @@ -103,20 +102,20 @@ def run_test (self): # 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')}) + fee = conventional_fee(2) + recipients = [{"address": myzaddr, "amount": Decimal('1.23456789')}] - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 10, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent') + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 10, fee, 'AllowFullyTransparent') 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.", + "When shielding coinbase funds, the wallet does not allow any change. The proposed transaction would result in 8.76533211 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") params = error_result["params"] - assert_equal(params["fee"], LEGACY_DEFAULT_FEE) # default + assert_equal(params["fee"], fee) assert_equal(params["minconf"], Decimal('10')) # default assert_equal(params["fromaddress"], mytaddr) assert_equal(params["amounts"][0]["address"], myzaddr) @@ -126,12 +125,11 @@ def run_test (self): myviewingkey = self.nodes[0].z_exportviewingkey(myzaddr) self.nodes[3].z_importviewingkey(myviewingkey, "no") - # This send will succeed. We send two coinbase utxos totalling 20.0 less a default fee, with no change. - # (This tx fits within the block unpaid action limit.) - shieldvalue = Decimal('20.0') - LEGACY_DEFAULT_FEE - recipients = [] - recipients.append({"address":myzaddr, "amount": shieldvalue}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 10, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + # This send will succeed. We send two coinbase utxos totalling 20.0 less fee, with no change. + fee = conventional_fee(4) + shieldvalue = Decimal('20.0') - fee + recipients = [{"address": myzaddr, "amount": shieldvalue}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 10, fee, 'AllowRevealedSenders') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() @@ -191,9 +189,10 @@ def run_test (self): # A custom fee of 0 is okay. Here the node will send the note value back to itself. # (This tx fits within the block unpaid action limit.) - recipients = [] - recipients.append({"address":myzaddr, "amount": saplingvalue}) - myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, Decimal('0.0')) + fee = conventional_fee(2) + saplingvalue -= fee + recipients = [{"address": myzaddr, "amount": saplingvalue}] + myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, fee) mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) @@ -207,10 +206,10 @@ def run_test (self): check_value_pool(self.nodes[0], 'sapling', saplingvalue) # convert note to transparent funds + fee = conventional_fee(3) unshieldvalue = Decimal('10.0') - recipients = [] - recipients.append({"address":mytaddr, "amount": unshieldvalue}) - myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') + recipients = [{"address": mytaddr, "amount": unshieldvalue}] + myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, fee, 'AllowRevealedRecipients') mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) assert(mytxid is not None) @@ -219,7 +218,7 @@ def run_test (self): self.sync_all() # check balances - saplingvalue -= unshieldvalue + LEGACY_DEFAULT_FEE + saplingvalue -= unshieldvalue + fee resp = self.nodes[0].z_gettotalbalance() assert_equal(Decimal(resp["transparent"]), Decimal('30.0')) assert_equal(Decimal(resp["private"]), saplingvalue) @@ -229,10 +228,10 @@ def run_test (self): # 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. # At this point in time, unspent notes all have a value of 10.0. - recipients = [] - amount = Decimal('10.0') - conventional_fee(2) - 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, 1) + fee = conventional_fee(2) + amount = Decimal('10.0') - fee - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold + recipients = [{"address": self.nodes[0].getnewaddress(), "amount": amount}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee) 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); note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") # Send will fail because send amount is too big, even when including coinbase utxos @@ -244,12 +243,11 @@ def run_test (self): assert_equal("Insufficient funds" in errorString, True) # z_sendmany will fail because of insufficient funds - recipients = [] - recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1) + recipients = [{"address": self.nodes[1].getnewaddress(), "amount": Decimal('10000.0')}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 10.00, need 10000.0001; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") - myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') - 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, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") + myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, fee, 'AllowRevealedRecipients') + wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 9.99955, need 10000.0001; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.") # Send will fail because of insufficient funds unless sender uses coinbase utxos try: @@ -268,7 +266,7 @@ def run_test (self): start_time = timeit.default_timer() for i in range(0,num_t_recipients): newtaddr = self.nodes[2].getnewaddress() - recipients.append({"address":newtaddr, "amount":amount_per_recipient}) + recipients.append({"address": newtaddr, "amount": amount_per_recipient}) elapsed = timeit.default_timer() - start_time print("...invoked getnewaddress() {} times in {} seconds".format(num_t_recipients, elapsed)) @@ -343,11 +341,13 @@ def run_test (self): amount_per_recipient = Decimal('0.002') minconf = 1 send_amount = num_recipients * amount_per_recipient - custom_fee = Decimal('0.00012345') + custom_fee = Decimal('0.00023456') + assert custom_fee >= conventional_fee(4) zbalance = self.nodes[0].z_getbalance(myzaddr) - for i in range(0,num_recipients): + for i in range(0, num_recipients): newzaddr = self.nodes[2].z_getnewaddress('sapling') - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) + 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) self.sync_all() diff --git a/qa/rpc-tests/wallet_treestate.py b/qa/rpc-tests/wallet_treestate.py index 934c74bd60b..4cd8f8f3306 100755 --- a/qa/rpc-tests/wallet_treestate.py +++ b/qa/rpc-tests/wallet_treestate.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Zcash developers +# Copyright (c) 2016-2024 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, initialize_chain_clean, \ start_nodes, connect_nodes_bi, wait_and_assert_operationid_status, \ - get_coinbase_address, LEGACY_DEFAULT_FEE + get_coinbase_address from test_framework.zip317 import conventional_fee import time @@ -21,7 +21,6 @@ def setup_chain(self): # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-regtestshieldcoinbase', '-debug=zrpc', '-allowdeprecated=z_getnewaddress', @@ -45,19 +44,20 @@ def run_test (self): myzaddr = self.nodes[0].z_getnewaddress() # Spend coinbase utxos to create three notes of 10 ZEC minus default fee each - recipients = [] - recipients.append({"address": myzaddr, "amount": Decimal('10.0') - LEGACY_DEFAULT_FEE}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + amount = Decimal('10.0') - fee + recipients = [{"address": myzaddr, "amount": amount}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) self.sync_all() - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) self.sync_all() - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[1].generate(1) @@ -65,24 +65,25 @@ def run_test (self): # Check balance resp = self.nodes[0].z_getbalance(myzaddr) - assert_equal(Decimal(resp), (Decimal('10.0') - LEGACY_DEFAULT_FEE) * 3) + assert_equal(Decimal(resp), amount * 3) # We want to test a real-world situation where during the time spent creating a transaction # with joinsplits, other transactions containing joinsplits have been mined into new blocks, # which result in the treestate changing whilst creating the transaction. # Tx 1 will change the treestate while Tx 2 containing chained joinsplits is still being generated - recipients = [] - recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('10.0') - LEGACY_DEFAULT_FEE}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + amount = Decimal('10.0') - fee + recipients = [{"address": self.nodes[2].z_getnewaddress(), "amount": amount}] + myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], myopid) # Tx 2 will consume all three notes, which must take at least two joinsplits. This is regardless of # the z_sendmany implementation because there are only two inputs per joinsplit. recipients = [] recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('18.0')}) - recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('12.0') - 4 * conventional_fee(3)}) - myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1) + recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('12.0') - 4*fee}) + myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, fee) # Wait for Tx 2 to begin executing... for x in range(1, 60): diff --git a/qa/rpc-tests/wallet_unified_change.py b/qa/rpc-tests/wallet_unified_change.py index a027363cef9..afd6561f96a 100755 --- a/qa/rpc-tests/wallet_unified_change.py +++ b/qa/rpc-tests/wallet_unified_change.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Zcash developers +# Copyright (c) 2022-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - LEGACY_DEFAULT_FEE, NU5_BRANCH_ID, assert_equal, get_coinbase_address, @@ -14,6 +13,8 @@ start_nodes, wait_and_assert_operationid_status, ) +from test_framework.mininode import COIN +from test_framework.zip317 import conventional_fee, ZIP_317_FEE # Test wallet accounts behaviour class WalletUnifiedChangeTest(BitcoinTestFramework): @@ -23,7 +24,6 @@ def __init__(self): def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 201), ]] * self.num_nodes) @@ -42,12 +42,14 @@ def run_test(self): ua1 = self.nodes[1].z_getaddressforaccount(account1)['address'] # Fund both of ua0_sapling and ua0_orchard - recipients = [{'address': ua0_sapling, 'amount': Decimal('9.99999000')}] - opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + fee = conventional_fee(3) + amount = Decimal('10') - fee + recipients = [{'address': ua0_sapling, 'amount': amount}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], opid) - recipients = [{'address': ua0_orchard, 'amount': Decimal('9.99999000')}] - opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedSenders') + recipients = [{'address': ua0_orchard, 'amount': amount}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[0], opid) self.sync_all() @@ -55,18 +57,18 @@ def run_test(self): self.sync_all() assert_equal( - {'pools': {'sapling': {'valueZat': 999999000}, 'orchard': {'valueZat': 999999000}}, 'minimum_confirmations': 1}, + {'pools': {'sapling': {'valueZat': amount * COIN}, 'orchard': {'valueZat': amount * COIN}}, 'minimum_confirmations': 1}, self.nodes[0].z_getbalanceforaccount(account0)) # Send both amounts to ua1 in fully-shielded transactions. This will result # in account1 having both Sapling and Orchard balances. recipients = [{'address': ua1_sapling, 'amount': 5}] - opid = self.nodes[0].z_sendmany(ua0_sapling, recipients, 1, LEGACY_DEFAULT_FEE) + opid = self.nodes[0].z_sendmany(ua0_sapling, recipients, 1, ZIP_317_FEE) txid_sapling = wait_and_assert_operationid_status(self.nodes[0], opid) recipients = [{'address': ua1, 'amount': 5}] - opid = self.nodes[0].z_sendmany(ua0_orchard, recipients, 1, LEGACY_DEFAULT_FEE) + opid = self.nodes[0].z_sendmany(ua0_orchard, recipients, 1, ZIP_317_FEE) txid_orchard = wait_and_assert_operationid_status(self.nodes[0], opid) assert_equal(set([txid_sapling, txid_orchard]), set(self.nodes[0].getrawmempool())) @@ -79,13 +81,15 @@ def run_test(self): assert_equal(1, self.nodes[0].gettransaction(txid_orchard)['confirmations']) assert_equal(1, self.nodes[0].gettransaction(txid_sapling)['confirmations']) - assert_equal( - {'pools': {'sapling': {'valueZat': 500000000}, 'orchard': {'valueZat': 500000000}}, 'minimum_confirmations': 1}, - self.nodes[1].z_getbalanceforaccount(account1)) + assert_equal({ + 'pools': {'sapling': {'valueZat': 500000000}, 'orchard': {'valueZat': 500000000}}, + 'minimum_confirmations': 1, + }, self.nodes[1].z_getbalanceforaccount(account1)) # Now send sapling->sapling, generating change. recipients = [{'address': ua0_sapling, 'amount': Decimal('2.5')}] - opid = self.nodes[1].z_sendmany(ua1_sapling, recipients, 1, 0) + fee = conventional_fee(2) + opid = self.nodes[1].z_sendmany(ua1_sapling, recipients, 1, fee) txid_sapling = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() @@ -94,23 +98,25 @@ def run_test(self): # Since this is entirely sapling->sapling, change should be returned # to the Sapling pool. - assert_equal( - {'pools': {'sapling': {'valueZat': 250000000}, 'orchard': {'valueZat': 500000000}}, 'minimum_confirmations': 1}, - self.nodes[1].z_getbalanceforaccount(account1)) + assert_equal({ + 'pools': {'sapling': {'valueZat': 250000000 - fee*COIN}, 'orchard': {'valueZat': 500000000}}, + 'minimum_confirmations': 1, + }, self.nodes[1].z_getbalanceforaccount(account1)) # If we send from an unrestricted UA, change should still not cross # the pool boundary, since we can build a purely sapling->sapling tx. recipients = [{'address': ua0_sapling, 'amount': Decimal('1.25')}] - opid = self.nodes[1].z_sendmany(ua1, recipients, 1, 0) + opid = self.nodes[1].z_sendmany(ua1, recipients, 1, fee) txid_sapling = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() self.nodes[1].generate(1) self.sync_all() - assert_equal( - {'pools': {'sapling': {'valueZat': 125000000}, 'orchard': {'valueZat': 500000000}}, 'minimum_confirmations': 1}, - self.nodes[1].z_getbalanceforaccount(account1)) + assert_equal({ + 'pools': {'sapling': {'valueZat': 125000000 - 2*fee*COIN}, 'orchard': {'valueZat': 500000000}}, + 'minimum_confirmations': 1, + }, self.nodes[1].z_getbalanceforaccount(account1)) if __name__ == '__main__': WalletUnifiedChangeTest().main() diff --git a/qa/rpc-tests/wallet_z_sendmany.py b/qa/rpc-tests/wallet_z_sendmany.py index b79239e2747..10ddbd0b5f5 100755 --- a/qa/rpc-tests/wallet_z_sendmany.py +++ b/qa/rpc-tests/wallet_z_sendmany.py @@ -1,11 +1,10 @@ #!/usr/bin/env python3 -# Copyright (c) 2020 The Zcash developers +# Copyright (c) 2020-2024 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 ( - LEGACY_DEFAULT_FEE, NU5_BRANCH_ID, assert_equal, assert_greater_than, @@ -18,6 +17,8 @@ ) from test_framework.authproxy import JSONRPCException from test_framework.mininode import COIN +from test_framework.zip317 import conventional_fee, ZIP_317_FEE + from decimal import Decimal # Test wallet address behaviour across network upgrades @@ -28,7 +29,6 @@ def __init__(self): def setup_network(self, split=False): self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', nuparams(NU5_BRANCH_ID, 238), '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', @@ -41,7 +41,7 @@ def setup_network(self, split=False): self.is_network_split=False self.sync_all() - # Check we only have balances in the expected pools. + # Check that an account has expected balances in only 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) @@ -54,6 +54,8 @@ def _check_balance_for_rpc(self, rpcmethod, node, account, expected, minconf): assert_equal(actual['minimum_confirmations'], minconf) return total_balance + # Check that an account has expected balances in only the expected pools, and that + # they are held only in `address`. 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) @@ -63,86 +65,76 @@ def check_balance(self, node, account, address, expected, minconf=1): def run_test(self): # z_sendmany is expected to fail if tx size breaks limit - myzaddr = self.nodes[0].z_getnewaddress() + n0sapling = self.nodes[0].z_getnewaddress() recipients = [] num_t_recipients = 1000 num_z_recipients = 2100 amount_per_recipient = Decimal('0.00000001') errorString = '' - for i in range(0,num_t_recipients): + for i in range(0, num_t_recipients): newtaddr = self.nodes[2].getnewaddress() - recipients.append({"address":newtaddr, "amount":amount_per_recipient}) - for i in range(0,num_z_recipients): + recipients.append({"address": newtaddr, "amount": amount_per_recipient}) + for i in range(0, num_z_recipients): newzaddr = self.nodes[2].z_getnewaddress() - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) - - # Issue #2759 Workaround START - # HTTP connection to node 0 may fall into a state, during the few minutes it takes to process - # loop above to create new addresses, that when z_sendmany is called with a large amount of - # rpc data in recipients, the connection fails with a 'broken pipe' error. Making a RPC call - # to node 0 before calling z_sendmany appears to fix this issue, perhaps putting the HTTP - # connection into a good state to handle a large amount of data in recipients. - self.nodes[0].getinfo() - # Issue #2759 Workaround END + recipients.append({"address": newzaddr, "amount": amount_per_recipient}) try: - self.nodes[0].z_sendmany(myzaddr, recipients) + self.nodes[0].z_sendmany(n0sapling, recipients) except JSONRPCException as e: errorString = e.error['message'] assert("size of raw transaction would be larger than limit" in errorString) # add zaddr to node 2 - myzaddr = self.nodes[2].z_getnewaddress() + n2saddr = self.nodes[2].z_getnewaddress() # add taddr to node 2 - mytaddr = self.nodes[2].getnewaddress() + n2taddr = self.nodes[2].getnewaddress() # send from node 0 to node 2 taddr - mytxid = self.nodes[0].sendtoaddress(mytaddr, 10.0) + mytxid = self.nodes[0].sendtoaddress(n2taddr, Decimal('10')) + self.sync_all() self.nodes[0].generate(10) self.sync_all() # send node 2 taddr to zaddr - recipients = [] - recipients.append({"address":myzaddr, "amount":7}) - opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowFullyTransparent') + zsendmanynotevalue = Decimal('7.0') + fee = conventional_fee(3) + recipients = [{"address": n2saddr, "amount": zsendmanynotevalue}] + opid = self.nodes[2].z_sendmany(n2taddr, recipients, 1, fee, 'AllowFullyTransparent') mytxid = wait_and_assert_operationid_status(self.nodes[2], opid) self.sync_all() - - # check balances - zsendmanynotevalue = Decimal('7.0') - zsendmanyfee = LEGACY_DEFAULT_FEE - node2sproutbalance = Decimal('50.00000000') - node2utxobalance = Decimal('210.00000000') - zsendmanynotevalue - zsendmanyfee + n2sprout_balance = Decimal('50.00000000') # check shielded balance status with getwalletinfo wallet_info = self.nodes[2].getwalletinfo() assert_equal(Decimal(wallet_info["shielded_unconfirmed_balance"]), zsendmanynotevalue) - assert_equal(Decimal(wallet_info["shielded_balance"]), node2sproutbalance) + assert_equal(Decimal(wallet_info["shielded_balance"]), n2sprout_balance) self.nodes[2].generate(10) self.sync_all() - assert_equal(self.nodes[2].getbalance(), node2utxobalance) - assert_equal(self.nodes[2].getbalance("*"), node2utxobalance) + n0t_balance = self.nodes[0].getbalance() + n2t_balance = Decimal('210.00000000') - zsendmanynotevalue - fee + assert_equal(Decimal(self.nodes[2].getbalance()), n2t_balance) + assert_equal(Decimal(self.nodes[2].getbalance("*")), n2t_balance) # check zaddr balance with z_getbalance - zbalance = zsendmanynotevalue - assert_equal(self.nodes[2].z_getbalance(myzaddr), zbalance) + n2saddr_balance = zsendmanynotevalue + assert_equal(self.nodes[2].z_getbalance(n2saddr), n2saddr_balance) # check via z_gettotalbalance resp = self.nodes[2].z_gettotalbalance() - assert_equal(Decimal(resp["transparent"]), node2utxobalance) - assert_equal(Decimal(resp["private"]), node2sproutbalance + zbalance) - assert_equal(Decimal(resp["total"]), node2utxobalance + node2sproutbalance + zbalance) + assert_equal(Decimal(resp["transparent"]), n2t_balance) + assert_equal(Decimal(resp["private"]), n2sprout_balance + n2saddr_balance) + assert_equal(Decimal(resp["total"]), n2t_balance + n2sprout_balance + n2saddr_balance) # check confirmed shielded balance with getwalletinfo wallet_info = self.nodes[2].getwalletinfo() assert_equal(Decimal(wallet_info["shielded_unconfirmed_balance"]), Decimal('0.0')) - assert_equal(Decimal(wallet_info["shielded_balance"]), node2sproutbalance + zsendmanynotevalue) + assert_equal(Decimal(wallet_info["shielded_balance"]), n2sprout_balance + n2saddr_balance) # there should be at least one Sapling output mytxdetails = self.nodes[2].getrawtransaction(mytxid, 1) @@ -150,53 +142,51 @@ def run_test(self): # the Sapling output should take in all the public value assert_equal(mytxdetails["valueBalance"], -zsendmanynotevalue) - # send from private note to node 0 and node 2 - node0balance = self.nodes[0].getbalance() - # The following assertion fails nondeterministically - # assert_equal(node0balance, Decimal('25.99798873')) - node2balance = self.nodes[2].getbalance() - # The following assertion might fail nondeterministically - # assert_equal(node2balance, Decimal('16.99799000')) - # try sending with a memo to a taddr, which should fail - recipients = [{"address":self.nodes[0].getnewaddress(), "amount":1, "memo":"DEADBEEF"}] - opid = self.nodes[2].z_sendmany(myzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') + recipients = [{"address": self.nodes[0].getnewaddress(), "amount": Decimal('1'), "memo": "DEADBEEF"}] + opid = self.nodes[2].z_sendmany(n2saddr, recipients, 1, ZIP_317_FEE, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', 'Failed to build transaction: Memos cannot be sent to transparent addresses.') - recipients = [] - recipients.append({"address":self.nodes[0].getnewaddress(), "amount":1}) - recipients.append({"address":self.nodes[2].getnewaddress(), "amount":1.0}) + fee = conventional_fee(4) + recipients = [ + {"address": self.nodes[0].getnewaddress(), "amount": Decimal('1')}, + {"address": self.nodes[2].getnewaddress(), "amount": Decimal('1')}, + ]; - opid = self.nodes[2].z_sendmany(myzaddr, recipients, 1, LEGACY_DEFAULT_FEE, 'AllowRevealedRecipients') + opid = self.nodes[2].z_sendmany(n2saddr, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[2], opid) - zbalance -= Decimal('2.0') + zsendmanyfee + n2saddr_balance -= Decimal('2') + fee + n0t_balance += Decimal('1') + n2t_balance += Decimal('1') self.sync_all() self.nodes[2].generate(1) self.sync_all() + n0t_balance += Decimal('10') # newly mature - node0balance += Decimal('11.0') - node2balance += Decimal('1.0') - assert_equal(Decimal(self.nodes[0].getbalance()), node0balance) - assert_equal(Decimal(self.nodes[0].getbalance("*")), node0balance) - assert_equal(Decimal(self.nodes[2].getbalance()), node2balance) - assert_equal(Decimal(self.nodes[2].getbalance("*")), node2balance) + assert_equal(Decimal(self.nodes[0].getbalance()), n0t_balance) + assert_equal(Decimal(self.nodes[0].getbalance("*")), n0t_balance) + assert_equal(Decimal(self.nodes[2].getbalance()), n2t_balance) + assert_equal(Decimal(self.nodes[2].getbalance("*")), n2t_balance) + assert_equal(self.nodes[2].z_getbalance(n2saddr), n2saddr_balance) - # 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)['address'] + # Get a new unified account on node 0 & generate a UA + n0account = self.nodes[0].z_getnewaccount()['account'] + n0ua0 = self.nodes[0].z_getaddressforaccount(n0account)['address'] + n0ua0_balance = Decimal('0') + self.check_balance(0, 0, n0ua0, {}) # Prepare to fund the UA from coinbase source = get_coinbase_address(self.nodes[2]) - recipients = [] - recipients.append({"address":n0ua0, "amount":10}) + fee = conventional_fee(3) + recipients = [{"address": n0ua0, "amount": Decimal('10') - fee}] # 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. unified_address_msg = 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.' revealed_senders_msg = 'Insufficient funds: have 0.00, need 10.00; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker.' - opid = self.nodes[2].z_sendmany(source, recipients, 1, 0) + opid = self.nodes[2].z_sendmany(source, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', unified_address_msg) # We can't create a transaction with an unknown privacy policy. @@ -204,7 +194,7 @@ def run_test(self): JSONRPCException, 'Unknown privacy policy name \'ZcashIsAwesome\'', self.nodes[2].z_sendmany, - source, recipients, 1, 0, 'ZcashIsAwesome') + source, recipients, 1, fee, 'ZcashIsAwesome') # If we set any policy that does not include AllowRevealedSenders, # z_sendmany also fails. @@ -213,31 +203,33 @@ def run_test(self): ('AllowRevealedAmounts', revealed_senders_msg), ('AllowRevealedRecipients', revealed_senders_msg), ]: - opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, policy) + opid = self.nodes[2].z_sendmany(source, recipients, 1, fee, policy) wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', msg) # By setting the correct policy, we can create the transaction. - opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, 'AllowRevealedSenders') + opid = self.nodes[2].z_sendmany(source, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[2], opid) + n2t_balance -= Decimal('10.0') + n0ua0_balance += Decimal('10') - fee + self.sync_all() self.nodes[2].generate(1) self.sync_all() + n0t_balance += Decimal('10.0') # newly mature - 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}) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(Decimal(self.nodes[0].getbalance()), n0t_balance) + assert_equal(Decimal(self.nodes[2].getbalance()), n2t_balance) # Send some funds to a specific legacy taddr that we can spend from - recipients = [] - recipients.append({"address":mytaddr, "amount":5}) + fee = conventional_fee(3) + recipients = [{"address": n2taddr, "amount": Decimal('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. revealed_recipients_msg = "This transaction would have transparent recipients, which is not enabled by default because it will publicly reveal transaction recipients and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway." - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0) + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], opid, 'failed', revealed_recipients_msg) # If we set any policy that does not include AllowRevealedRecipients, @@ -248,60 +240,68 @@ def run_test(self): 'AllowRevealedSenders', 'AllowLinkingAccountAddresses', ]: - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, policy) + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee, policy) wait_and_assert_operationid_status(self.nodes[0], opid, 'failed', revealed_recipients_msg) # By setting the correct policy, we can create the transaction. - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, 'AllowRevealedRecipients') + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee, 'AllowRevealedRecipients') wait_and_assert_operationid_status(self.nodes[0], opid) + n2t_balance += Decimal('5') + n0ua0_balance -= Decimal('5') + fee + self.sync_all() 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) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(Decimal(self.nodes[2].getbalance()), n2t_balance) # 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) + fee = conventional_fee(2) + recipients = [{"address": n2saddr, "amount": Decimal('3')}] + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], opid) + n2saddr_balance += Decimal('3') + n0ua0_balance -= Decimal('3') + fee + self.sync_all() 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) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(self.nodes[2].z_getbalance(n2saddr), n2saddr_balance) # 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') + fee = conventional_fee(3) + recipients = [{"address": n0ua0, "amount": Decimal('4')}] + opid = self.nodes[2].z_sendmany(n2taddr, recipients, 1, fee, 'AllowFullyTransparent') wait_and_assert_operationid_status(self.nodes[2], opid) + n0ua0_balance += Decimal('4') + n2t_balance -= Decimal('4') + fee + self.sync_all() 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) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(Decimal(self.nodes[2].getbalance()), n2t_balance) # 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) + fee = conventional_fee(2) + recipients = [{"address": n0ua0, "amount": Decimal('2')}] + opid = self.nodes[2].z_sendmany(n2saddr, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[2], opid) + n0ua0_balance += Decimal('2') + n2saddr_balance -= Decimal('2') + fee + self.sync_all() 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) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(self.nodes[2].z_getbalance(n2saddr), n2saddr_balance) # # Test that z_sendmany avoids UA linkability unless we allow it. @@ -317,26 +317,34 @@ def run_test(self): taddr = self.nodes[1].z_listunifiedreceivers(ua)['p2pkh'] self.nodes[0].sendtoaddress(taddr, 2) + n0sapling_balance = n0ua0_balance + n1ua0_balance = Decimal('2') + n1ua1_balance = Decimal('2') + n1t_balance = n1ua0_balance + n1ua1_balance + self.sync_all() self.nodes[2].generate(1) self.sync_all() + self.check_balance(0, 0, n0ua0, {'sapling': n0sapling_balance}) + # The account should see all funds. - assert_equal( - self.nodes[1].z_getbalanceforaccount(n1account)['pools'], - {'transparent': {'valueZat': 4 * COIN}}, - ) + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'transparent': {'valueZat': n1t_balance * 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) + assert_equal(Decimal(self.nodes[1].z_getbalance(n1ua0)), n1ua0_balance) + assert_equal(Decimal(self.nodes[1].z_getbalance(n1ua1)), n1ua1_balance) - # If we try to send 3 ZEC from n1ua0, it will fail with too-few funds. - recipients = [{"address":n0ua0, "amount":3}] + # If we try to send 3 ZEC less fee from n1ua0, it will fail with insufficient funds. + fee = conventional_fee(4) + amount = Decimal('3') - fee + recipients = [{"address": n0ua0, "amount": amount}] linked_addrs_with_coinbase_note_msg = 'Insufficient funds: have 0.00, need 3.00; note that coinbase outputs will not be selected if you specify ANY_TADDR, any transparent recipients are included, or if the `privacyPolicy` parameter is not set to `AllowRevealedSenders` or weaker. (This transaction may require selecting transparent coins that were sent to multiple addresses, which is not enabled by default because it would create a public link between those 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.)' linked_addrs_without_coinbase_note_msg = 'Insufficient funds: have 2.00, need 3.00. (This transaction may require selecting transparent coins that were sent to multiple addresses, which is not enabled by default because it would create a public link between those 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.)' revealed_amounts_msg = 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.' - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0) + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', revealed_amounts_msg) # If we try it again with any policy that is too strong, it also fails. @@ -347,45 +355,50 @@ def run_test(self): ('AllowRevealedSenders', linked_addrs_without_coinbase_note_msg), ('AllowFullyTransparent', linked_addrs_without_coinbase_note_msg), ]: - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy) + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, policy) wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg) # If we try to send just a bit less than we have, it will fail, complaining about dust - opid = self.nodes[1].z_sendmany(n1ua0, [{"address":n0ua0, "amount":3.9999999}], 1, 0, 'AllowLinkingAccountAddresses') + opid = self.nodes[1].z_sendmany(n1ua0, + [{"address": n0ua0, "amount": Decimal('3.9999999') - fee}], + 1, fee, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', 'Insufficient funds: have 4.00, need 0.00000044 more to avoid creating invalid change output 0.0000001 (dust threshold is 0.00000054).') - # Once we provide a sufficiently-weak policy, the transaction succeeds. - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowLinkingAccountAddresses') + # Once we provide a sufficiently weak policy, the transaction succeeds. + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, 'AllowLinkingAccountAddresses') wait_and_assert_operationid_status(self.nodes[1], opid) + n0ua0_balance += amount + # Change should be sent to the Sapling change address (because NU5 is not active). + n1sapling_balance = n1t_balance - amount - fee + del n0sapling_balance + del n1t_balance 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}}, - ) + self.check_balance(0, 0, n0ua0, {'sapling': n0ua0_balance}) + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'sapling': {'valueZat': n1sapling_balance * 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) + # z_getbalance behaves inconsistently between transparent and shielded + # addresses: for a shielded address it gives the account balance. + assert_equal(Decimal(self.nodes[1].z_getbalance(n1ua0)), n1sapling_balance) + assert_equal(Decimal(self.nodes[1].z_getbalance(n1ua1)), n1sapling_balance) # # Test Orchard-only UA before NU5 # - n0orchard_only = self.nodes[0].z_getaddressforaccount(n0account0, ["orchard"])['address'] - recipients = [{"address":n0orchard_only, "amount":1}] + n0orchard_only = self.nodes[0].z_getaddressforaccount(n0account, ["orchard"])['address'] + recipients = [{"address": n0orchard_only, "amount": Decimal('1')}] for (policy, msg) in [ ('FullPrivacy', 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.'), ('AllowRevealedAmounts', 'This transaction would send to a transparent receiver of a unified address, which is not enabled by default because it will publicly reveal transaction recipients and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway.'), ('AllowRevealedRecipients', 'Could not send to an Orchard-only receiver despite a lax privacy policy, because NU5 has not been activated yet.'), ]: - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy) + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, policy) wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg) # @@ -394,26 +407,34 @@ def run_test(self): # Send some legacy transparent funds to n1ua0, creating Sapling outputs. source = get_coinbase_address(self.nodes[2]) - recipients = [{"address":n1ua0, "amount":10}] + fee = conventional_fee(3) + recipients = [{"address": n1ua0, "amount": Decimal('10') - fee}] # This requires the AllowRevealedSenders policy, but we specify only AllowRevealedAmounts... - opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, 'AllowRevealedAmounts') + opid = self.nodes[2].z_sendmany(source, recipients, 1, fee, 'AllowRevealedAmounts') 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(source, recipients, 1, 0, 'NoPrivacy') + opid = self.nodes[2].z_sendmany(source, recipients, 1, fee, 'NoPrivacy') wait_and_assert_operationid_status(self.nodes[2], opid) + n1sapling_balance += Decimal('10') - fee self.sync_all() self.nodes[2].generate(1) self.sync_all() + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'sapling': {'valueZat': n1sapling_balance * COIN}, + }) + # Send some funds from node 1's account to a transparent address. - recipients = [{"address":mytaddr, "amount":5}] + fee = conventional_fee(3) + recipients = [{"address": n2taddr, "amount": Decimal('5')}] # This requires the AllowRevealedRecipients policy... - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0) + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', revealed_recipients_msg) # ... which we can always override with the NoPrivacy policy. - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'NoPrivacy') + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, 'NoPrivacy') wait_and_assert_operationid_status(self.nodes[1], opid) + n1sapling_balance -= Decimal('5') + fee # Activate NU5 @@ -421,80 +442,94 @@ def run_test(self): self.nodes[1].generate(10) self.sync_all() + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'sapling': {'valueZat': n1sapling_balance * COIN}, + }) + # # Test sending Sprout funds to Orchard-only UA # sproutAddr = self.nodes[2].listaddresses()[0]['sprout']['addresses'][0] - recipients = [{"address":n0orchard_only, "amount":100}] + recipients = [{"address": n0orchard_only, "amount": Decimal('100')}] for (policy, msg) in [ ('FullPrivacy', 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.'), ('AllowRevealedAmounts', 'This transaction would send to a transparent receiver of a unified address, which is not enabled by default because it will publicly reveal transaction recipients and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway.'), ('AllowRevealedRecipients', 'Could not send to an Orchard-only receiver despite a lax privacy policy, because you are sending from the Sprout pool and there is no transaction version that supports both Sprout and Orchard.'), + ('NoPrivacy', 'Could not send to an Orchard-only receiver despite a lax privacy policy, because you are sending from the Sprout pool and there is no transaction version that supports both Sprout and Orchard.'), ]: - opid = self.nodes[2].z_sendmany(sproutAddr, recipients, 1, 0, policy) + opid = self.nodes[2].z_sendmany(sproutAddr, recipients, 1, ZIP_317_FEE, policy) wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', msg) # # Test AllowRevealedAmounts policy # - assert_equal( - {'pools': {'sapling': {'valueZat': 600000000}}, 'minimum_confirmations': 1}, - self.nodes[1].z_getbalanceforaccount(n1account)) - - # Sending some funds to the Orchard pool in n0account0 ... - n0ua1 = self.nodes[0].z_getaddressforaccount(n0account0, ["orchard"])['address'] - recipients = [{"address":n0ua1, "amount": 6}] + # Sending some funds to the Orchard pool in n0account ... + n0ua1 = self.nodes[0].z_getaddressforaccount(n0account, ["orchard"])['address'] + fee = conventional_fee(4) + recipients = [{"address": n0ua1, "amount": Decimal('5')}] # Should fail under default and 'FullPrivacy' policies ... revealed_amounts_msg = 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.' - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0) + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', revealed_amounts_msg) - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'FullPrivacy') + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, 'FullPrivacy') wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', revealed_amounts_msg) - # Should succeed under 'AllowRevealedAmounts' - opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowRevealedAmounts') + # Should succeed under 'AllowRevealedAmounts'. The change will go to Orchard. + opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, fee, 'AllowRevealedAmounts') wait_and_assert_operationid_status(self.nodes[1], opid) + n0sapling_balance = n0ua0_balance + n0orchard_balance = Decimal('5') + n1orchard_balance = n1sapling_balance - Decimal('5') - fee + del n0ua0_balance + del n1sapling_balance self.sync_all() self.nodes[1].generate(1) self.sync_all() - assert_equal( - {'pools': {'sapling': {'valueZat': 1100000000}, 'orchard': {'valueZat': 600000000}}, 'minimum_confirmations': 1}, - self.nodes[0].z_getbalanceforaccount(n0account0)) + assert_equal(self.nodes[0].z_getbalanceforaccount(n0account)['pools'], { + 'sapling': {'valueZat': n0sapling_balance * COIN}, + 'orchard': {'valueZat': n0orchard_balance * COIN}, + }) + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'orchard': {'valueZat': n1orchard_balance * COIN}, + }) # A total that requires selecting from both pools should fail under default and # FullPrivacy policies... - recipients = [{"address":n1ua0, "amount": 15}] - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0) + fee = conventional_fee(3) + recipients = [{"address": n1ua0, "amount": Decimal('15')}] + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee) wait_and_assert_operationid_status(self.nodes[0], opid, 'failed', revealed_amounts_msg) - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, 'FullPrivacy') + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee, 'FullPrivacy') wait_and_assert_operationid_status(self.nodes[0], opid, 'failed', revealed_amounts_msg) # Should succeed under 'AllowRevealedAmounts' - opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, 'AllowRevealedAmounts') + # All funds should be received to the Orchard pool, and all change should + # be optimistically shielded. + fee = conventional_fee(6) + opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, fee, 'AllowRevealedAmounts') wait_and_assert_operationid_status(self.nodes[0], opid) + n0orchard_balance += n0sapling_balance - Decimal('15') - fee + n1orchard_balance += Decimal('15') + del n0sapling_balance self.sync_all() self.nodes[1].generate(1) self.sync_all() - # All funds should be received to the Orchard pool - assert_equal( - {'pools': {'orchard': {'valueZat': 1500000000}}, 'minimum_confirmations': 1}, - self.nodes[1].z_getbalanceforaccount(n1account)) - - # And all change should be optimistically shielded - assert_equal( - {'pools': {'orchard': {'valueZat': 200000000}}, 'minimum_confirmations': 1}, - self.nodes[0].z_getbalanceforaccount(n0account0)) - + assert_equal(self.nodes[0].z_getbalanceforaccount(n0account)['pools'], { + 'orchard': {'valueZat': n0orchard_balance * COIN}, + }) + assert_equal(self.nodes[1].z_getbalanceforaccount(n1account)['pools'], { + 'orchard': {'valueZat': n1orchard_balance * COIN}, + }) self.sync_all() self.nodes[1].generate(1) @@ -504,15 +539,25 @@ def run_test(self): # Test transparent change # - recipients = [{"address":n0ua1, "amount": 4}] + fee = conventional_fee(3) + recipients = [{"address": n0ua1, "amount": Decimal('4')}] # Should fail because this generates transparent change, but we don’t have # `AllowRevealedRecipients` - opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0, 'AllowRevealedSenders') + opid = self.nodes[2].z_sendmany(n2taddr, recipients, 1, fee, 'AllowRevealedSenders') wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', "This transaction would have transparent change, which is not enabled by default because it will publicly reveal the change address and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway.") # Should succeed once we include `AllowRevealedRecipients` - opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0, 'AllowFullyTransparent') + opid = self.nodes[2].z_sendmany(n2taddr, recipients, 1, fee, 'AllowFullyTransparent') wait_and_assert_operationid_status(self.nodes[2], opid) + n0orchard_balance += Decimal('4') + + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalanceforaccount(n0account)['pools'], { + 'orchard': {'valueZat': n0orchard_balance * COIN}, + }) if __name__ == '__main__': WalletZSendmanyTest().main() diff --git a/qa/rpc-tests/wallet_zip317_default.py b/qa/rpc-tests/wallet_zip317_default.py new file mode 100755 index 00000000000..60b8948c0ea --- /dev/null +++ b/qa/rpc-tests/wallet_zip317_default.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# Copyright (c) 2022-2024 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from decimal import Decimal + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.mininode import COIN +from test_framework.util import ( + CANOPY_BRANCH_ID, + NU5_BRANCH_ID, + assert_equal, + assert_raises_message, + get_coinbase_address, + nuparams, + start_nodes, + wait_and_assert_operationid_status, +) +from test_framework.zip317 import conventional_fee, ZIP_317_FEE + +# Regression test for https://github.com/zcash/zcash/issues/6956 . +class WalletZip317DefaultTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + + def setup_nodes(self): + return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[ + nuparams(CANOPY_BRANCH_ID, 205), + nuparams(NU5_BRANCH_ID, 206), + '-allowdeprecated=getnewaddress', + '-allowdeprecated=z_getnewaddress', + '-regtestwalletsetbestchaineveryblock', + ]] * self.num_nodes) + + def run_test(self): + # Sanity-check the test harness. + assert_equal(self.nodes[0].getblockcount(), 200) + + # Create an account with funds in the Sapling receiver. + acct0 = self.nodes[0].z_getnewaccount()['account'] + ua0 = self.nodes[0].z_getaddressforaccount(acct0, ['sapling', 'orchard'])['address'] + + coinbase_fee = conventional_fee(3) + balance0 = Decimal('10') - coinbase_fee + recipients = [{"address": ua0, "amount": balance0}] + opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, coinbase_fee, 'AllowRevealedSenders') + wait_and_assert_operationid_status(self.nodes[0], opid) + + # Mine the tx & activate NU5. + self.sync_all() + self.nodes[0].generate(10) + self.sync_all() + + assert_equal( + {'pools': {'sapling': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, + self.nodes[0].z_getbalanceforaccount(acct0), + ) + + acct1 = self.nodes[1].z_getnewaccount()['account'] + ua1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard'])['address'] + + # The next z_sendmany call fails when passed `None`/`ZIP_317_FEE` because it + # calculates a fee that is too low. + # https://github.com/zcash/zcash/issues/6956 + recipients = [{"address": ua1, "amount": Decimal('1')}] + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, ZIP_317_FEE, 'AllowRevealedAmounts') + # The buggy behaviour. + assert_raises_message(AssertionError, + "Transaction commit failed:: tx unpaid action limit exceeded: 1 action(s) exceeds limit of 0", + wait_and_assert_operationid_status, self.nodes[0], opid) + + # If we pass `fee` instead of `None`, it succeeds. + fee = conventional_fee(4) + opid = self.nodes[0].z_sendmany(ua0, recipients, 1, fee, 'AllowRevealedAmounts') + wait_and_assert_operationid_status(self.nodes[0], opid) + + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # The nodes have the expected split of funds. + balance0 -= Decimal('1') + fee + assert_equal( + {'pools': {'orchard': {'valueZat': balance0 * COIN}}, 'minimum_confirmations': 1}, + self.nodes[0].z_getbalanceforaccount(acct0), + ) + assert_equal( + {'pools': {'orchard': {'valueZat': 1_0000_0000}}, 'minimum_confirmations': 1}, + self.nodes[1].z_getbalanceforaccount(acct1), + ) + + # TODO: also test the case in `wallet_isfromme.py`. + +if __name__ == '__main__': + WalletZip317DefaultTest().main() diff --git a/qa/rpc-tests/zkey_import_export.py b/qa/rpc-tests/zkey_import_export.py index 13d7d1c0f0d..b60fe65e5fb 100755 --- a/qa/rpc-tests/zkey_import_export.py +++ b/qa/rpc-tests/zkey_import_export.py @@ -1,21 +1,23 @@ #!/usr/bin/env python3 -# Copyright (c) 2017 The Zcash developers +# Copyright (c) 2017-2024 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_greater_than, start_nodes,\ - initialize_chain_clean, connect_nodes_bi, wait_and_assert_operationid_status, \ - LEGACY_DEFAULT_FEE +from test_framework.authproxy import JSONRPCException +from test_framework.util import ( + assert_equal, assert_greater_than, assert_raises_message, start_nodes, + initialize_chain_clean, connect_nodes_bi, wait_and_assert_operationid_status, +) +from test_framework.zip317 import conventional_fee + from functools import reduce import logging import sys logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout) -fee = LEGACY_DEFAULT_FEE # constant (but can be changed within reason) - class ZkeyImportExportTest (BitcoinTestFramework): def setup_chain(self): @@ -24,7 +26,6 @@ def setup_chain(self): def setup_network(self, split=False): self.nodes = start_nodes(5, self.options.tmpdir, extra_args=[[ - '-minrelaytxfee=0', '-allowdeprecated=getnewaddress', '-allowdeprecated=z_getnewaddress', '-allowdeprecated=z_getbalance', @@ -39,28 +40,27 @@ def setup_network(self, split=False): self.sync_all() def run_test(self): - [alice, bob, charlie, david, miner] = self.nodes + [alice, bob, charlie, daira, miner] = self.nodes + fee = conventional_fee(2) # the sender loses 'amount' plus fee; to_addr receives exactly 'amount' def z_send(from_node, from_addr, to_addr, amount): - global fee - - opid = from_node.z_sendmany(from_addr, - [{"address": to_addr, "amount": Decimal(amount)}], 1, int(fee)) + recipients = [{"address": to_addr, "amount": amount}] + opid = from_node.z_sendmany(from_addr, recipients, 1, fee) wait_and_assert_operationid_status(from_node, opid) self.sync_all() miner.generate(1) self.sync_all() - def verify_utxos(node, amts, zaddr): - amts.sort(reverse=True) + def verify_utxos(node, amounts, zaddr): + amounts.sort(reverse=True) txs = node.z_listreceivedbyaddress(zaddr) txs.sort(key=lambda x: x["amount"], reverse=True) print("Sorted txs", txs) - print("amts", amts) + print("amounts", amounts) try: - assert_equal(amts, [tx["amount"] for tx in txs]) + assert_equal(amounts, [tx["amount"] for tx in txs]) for tx in txs: # make sure Sapling outputs exist and have valid values assert_equal("outindex" in tx, True) @@ -68,7 +68,7 @@ def verify_utxos(node, amts, zaddr): except AssertionError: logging.error( 'Expected amounts: %r; txs: %r', - amts, txs) + amounts, txs) raise def get_private_balance(node): @@ -91,8 +91,8 @@ def get_private_balance(node): # Now get a pristine z-address for receiving transfers: bob_zaddr = bob.z_getnewaddress() verify_utxos(bob, [], bob_zaddr) - # TODO: Verify that charlie doesn't have funds in addr - # verify_utxos(charlie, []) + assert_raises_message(JSONRPCException, "From address does not belong to this node", + charlie.z_listreceivedbyaddress, bob_zaddr) # the amounts of each txn embodied which generates a single UTXO: amounts = list(map(Decimal, ['2.3', '3.7', '0.1', '0.5', '1.0', '0.19'])) @@ -114,7 +114,8 @@ def get_private_balance(node): z_send(alice, alice_zaddr, bob_zaddr, amount) verify_utxos(bob, amounts[:4], bob_zaddr) - # verify_utxos(charlie, []) + assert_raises_message(JSONRPCException, "From address does not belong to this node", + charlie.z_listreceivedbyaddress, bob_zaddr) logging.info("Importing bob_privkey into charlie...") # z_importkey rescan defaults to "whenkeyisnew", so should rescan here @@ -141,26 +142,24 @@ def get_private_balance(node): verify_utxos(charlie, amounts, ipk_zaddr["address"]) verify_utxos(charlie, amounts, ipk_zaddr2["address"]) - # keep track of the fees incurred by bob (his sends) - bob_fee = Decimal("0") + # keep track of bob's expected balance + bob_balance = sum(amounts) # Try to reproduce zombie balance reported in #1936 # At generated zaddr, receive ZEC, and send ZEC back out. bob -> alice for amount in amounts[:2]: print("Sending amount from bob to alice: ", amount) z_send(bob, bob_zaddr, alice_zaddr, amount) - bob_fee += fee + bob_balance -= amount + fee - bob_balance = sum(amounts[2:]) - int(bob_fee) - assert_equal(bob.z_getbalance(bob_zaddr), bob_balance) - # z_import onto new node "david" (blockchain rescan, default or True?) - d_ipk_zaddr = david.z_importkey(bob_privkey) + # z_import onto new node "daira" (rescans by default because the key is new) + d_ipk_zaddr = daira.z_importkey(bob_privkey) - # Check if amt bob spent is deducted for charlie and david + # Check if amount bob spent is deducted for charlie and daira assert_equal(charlie.z_getbalance(ipk_zaddr["address"]), bob_balance) - assert_equal(david.z_getbalance(d_ipk_zaddr["address"]), bob_balance) + assert_equal(daira.z_getbalance(d_ipk_zaddr["address"]), bob_balance) if __name__ == '__main__': ZkeyImportExportTest().main() diff --git a/qa/supply-chain/audits.toml b/qa/supply-chain/audits.toml index 683f8c90e76..1b1a7c9f7d4 100644 --- a/qa/supply-chain/audits.toml +++ b/qa/supply-chain/audits.toml @@ -3044,7 +3044,7 @@ end = "2024-09-21" criteria = "safe-to-deploy" user-id = 169181 # Kris Nuttycombe (nuttycom) start = "2022-07-22" -end = "2024-09-21" +end = "2025-10-02" [[trusted.equihash]] criteria = "safe-to-deploy" @@ -3092,7 +3092,13 @@ end = "2024-09-21" criteria = "safe-to-deploy" user-id = 169181 # Kris Nuttycombe (nuttycom) start = "2023-02-28" -end = "2024-09-21" +end = "2025-10-02" + +[[trusted.incrementalmerkletree-testing]] +criteria = "safe-to-deploy" +user-id = 169181 # Kris Nuttycombe (nuttycom) +start = "2024-09-25" +end = "2025-10-02" [[trusted.orchard]] criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"] @@ -3106,12 +3112,24 @@ user-id = 1244 # ebfull start = "2022-10-19" end = "2024-09-21" +[[trusted.orchard]] +criteria = "safe-to-deploy" +user-id = 169181 # Kris Nuttycombe (nuttycom) +start = "2024-08-12" +end = "2025-10-02" + [[trusted.sapling-crypto]] criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"] user-id = 6289 # Jack Grigg (str4d) start = "2024-01-26" end = "2025-03-18" +[[trusted.sapling-crypto]] +criteria = ["safe-to-deploy", "crypto-reviewed"] +user-id = 169181 # Kris Nuttycombe (nuttycom) +start = "2024-08-12" +end = "2025-10-02" + [[trusted.windows-sys]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) @@ -3232,6 +3250,12 @@ user-id = 169181 # Kris Nuttycombe (nuttycom) start = "2024-08-20" end = "2025-08-26" +[[trusted.zcash_primitives]] +criteria = "safe-to-deploy" +user-id = 6289 # Jack Grigg (str4d) +start = "2021-03-26" +end = "2025-10-02" + [[trusted.zcash_proofs]] criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"] user-id = 6289 # Jack Grigg (str4d) @@ -3244,6 +3268,12 @@ user-id = 169181 # Kris Nuttycombe (nuttycom) start = "2024-08-20" end = "2025-08-26" +[[trusted.zcash_proofs]] +criteria = "safe-to-deploy" +user-id = 6289 # Jack Grigg (str4d) +start = "2021-03-26" +end = "2025-10-02" + [[trusted.zcash_protocol]] criteria = "safe-to-deploy" user-id = 169181 # Kris Nuttycombe (nuttycom) diff --git a/qa/supply-chain/config.toml b/qa/supply-chain/config.toml index 2346b168bdc..41aaf9eae09 100644 --- a/qa/supply-chain/config.toml +++ b/qa/supply-chain/config.toml @@ -346,10 +346,6 @@ criteria = "safe-to-deploy" version = "1.17.0" criteria = "safe-to-deploy" -[[exemptions.orchard]] -version = "0.9.0" -criteria = "safe-to-deploy" - [[exemptions.pairing]] version = "0.22.0" criteria = "safe-to-deploy" @@ -466,10 +462,6 @@ criteria = "safe-to-deploy" version = "0.3.0" criteria = "safe-to-deploy" -[[exemptions.sapling-crypto]] -version = "0.2.0" -criteria = "safe-to-deploy" - [[exemptions.secp256k1]] version = "0.26.0" criteria = "safe-to-deploy" @@ -570,10 +562,6 @@ criteria = "safe-to-deploy" version = "0.9.5" criteria = "safe-to-deploy" -[[exemptions.visibility]] -version = "0.1.1" -criteria = "safe-to-deploy" - [[exemptions.wait-timeout]] version = "0.2.0" criteria = "safe-to-deploy" @@ -638,10 +626,6 @@ criteria = "safe-to-deploy" version = "2.5.0" criteria = "safe-to-deploy" -[[exemptions.zcash_encoding]] -version = "0.2.1" -criteria = "safe-to-deploy" - [[exemptions.zerocopy]] version = "0.7.35" criteria = "safe-to-deploy" diff --git a/qa/supply-chain/imports.lock b/qa/supply-chain/imports.lock index 1bd8f97dd7d..efc9dcdc94a 100644 --- a/qa/supply-chain/imports.lock +++ b/qa/supply-chain/imports.lock @@ -2,8 +2,8 @@ # cargo-vet imports lock [[publisher.bridgetree]] -version = "0.5.0" -when = "2024-08-12" +version = "0.6.0" +when = "2024-09-25" user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" @@ -49,8 +49,29 @@ user-id = 1244 user-login = "ebfull" [[publisher.incrementalmerkletree]] -version = "0.6.0" -when = "2024-08-12" +version = "0.7.0" +when = "2024-09-25" +user-id = 169181 +user-login = "nuttycom" +user-name = "Kris Nuttycombe" + +[[publisher.incrementalmerkletree-testing]] +version = "0.1.0" +when = "2024-09-25" +user-id = 169181 +user-login = "nuttycom" +user-name = "Kris Nuttycombe" + +[[publisher.orchard]] +version = "0.10.0" +when = "2024-10-02" +user-id = 169181 +user-login = "nuttycom" +user-name = "Kris Nuttycombe" + +[[publisher.sapling-crypto]] +version = "0.3.0" +when = "2024-10-02" user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" @@ -133,11 +154,17 @@ user-login = "kennykerr" user-name = "Kenny Kerr" [[publisher.zcash_address]] -version = "0.5.0" -when = "2024-08-26" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" +version = "0.6.0" +when = "2024-10-02" +user-id = 6289 +user-login = "str4d" +user-name = "Jack Grigg" + +[[publisher.zcash_encoding]] +version = "0.2.0" +when = "2022-10-19" +user-id = 1244 +user-login = "ebfull" [[publisher.zcash_history]] version = "0.4.0" @@ -154,22 +181,22 @@ user-login = "nuttycom" user-name = "Kris Nuttycombe" [[publisher.zcash_primitives]] -version = "0.17.0" -when = "2024-08-26" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" +version = "0.19.0" +when = "2024-10-02" +user-id = 6289 +user-login = "str4d" +user-name = "Jack Grigg" [[publisher.zcash_proofs]] -version = "0.17.0" -when = "2024-08-26" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" +version = "0.19.0" +when = "2024-10-02" +user-id = 6289 +user-login = "str4d" +user-name = "Jack Grigg" [[publisher.zcash_protocol]] -version = "0.3.0" -when = "2024-08-26" +version = "0.4.0" +when = "2024-10-02" user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" @@ -1670,3 +1697,21 @@ who = "Jack Grigg " criteria = "safe-to-deploy" delta = "1.0.61 -> 1.0.63" aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.visibility]] +who = "Kris Nuttycombe " +criteria = "safe-to-deploy" +version = "0.1.1" +notes = """ +- Crate has no unsafe code, and sets `#![forbid(unsafe_code)]`. +- Crate has no powerful imports, and exclusively provides a proc macro + that safely malleates a visibility modifier. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.zcash_encoding]] +who = "Kris Nuttycombe " +criteria = "safe-to-deploy" +delta = "0.2.0 -> 0.2.1" +notes = "This release adds minor convenience methods and involves no unsafe code." +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" diff --git a/qa/zcash/postponed-updates.txt b/qa/zcash/postponed-updates.txt index fb99d734174..8b50e16962d 100644 --- a/qa/zcash/postponed-updates.txt +++ b/qa/zcash/postponed-updates.txt @@ -14,7 +14,9 @@ native_b2 1.86.0 2024-12-15 # Clang and Rust are currently pinned to LLVM 18 libcxx 19.1.0 2024-12-15 +libcxx 19.1.1 2024-12-15 native_clang 19.1.0 2024-12-15 +native_clang 19.1.1 2024-12-15 # We follow upstream Bitcoin Core's LevelDB updates leveldb 1.23 2024-12-15 diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 091c47d6aef..276ed3bfed7 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -140,8 +140,7 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_NU5].hashActivationBlock = uint256S("0000000000d723156d9b65ffcf4984da7a19675ed7e2f06d9e5d5188af087bf8"); consensus.vUpgrades[Consensus::UPGRADE_NU6].nProtocolVersion = 170120; - consensus.vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight = - Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + consensus.vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight = 2726400; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nProtocolVersion = 0x7FFFFFFF; consensus.vUpgrades[Consensus::UPGRADE_ZFUTURE].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; @@ -172,6 +171,10 @@ class CMainParams : public CChainParams { keyConstants.bech32mHRPs[TEX_ADDRESS] = "tex"; { + auto canopyActivation = consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight; + auto nu6Activation = consensus.vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight; + + // ZIP 214 Revision 0 std::vector bp_addresses = { "t3LmX1cxWPPPqL4TZHx42HU3U5ghbFjRiif", "t3Toxk1vJQ6UjWQ42tUJz2rV2feUWkpbTDs", @@ -231,18 +234,37 @@ class CMainParams : public CChainParams { consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_BP, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400, + canopyActivation, + nu6Activation, bp_addresses); consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_ZF, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400, + canopyActivation, + nu6Activation, zf_addresses); consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_MG, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400, + canopyActivation, + nu6Activation, mg_addresses); + + // ZIP 214 Revision 1 + // FPF uses a single address repeated 12 times, once for each funding period. + std::vector fpf_addresses(12, "t3cFfPt1Bcvgez9ZbMBFWeZsskxTkPzGCow"); + + consensus.AddZIP207FundingStream( + keyConstants, + Consensus::FS_FPF_ZCG, + nu6Activation, + 3146400, + fpf_addresses); + consensus.AddZIP207LockboxStream( + keyConstants, + Consensus::FS_DEFERRED, + nu6Activation, + 3146400); } // The best chain should have at least this much work. @@ -473,6 +495,10 @@ class CTestNetParams : public CChainParams { // Testnet funding streams { + auto canopyActivation = consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight; + auto nu6Activation = consensus.vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight; + + // ZIP 214 Revision 0 std::vector bp_addresses = { "t26ovBdKAJLtrvBsE2QGF4nqBkEuptuPFZz", "t26ovBdKAJLtrvBsE2QGF4nqBkEuptuPFZz", @@ -534,27 +560,32 @@ class CTestNetParams : public CChainParams { consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_BP, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2796000, + canopyActivation, + 2796000, // *not* the NU6 activation height bp_addresses); consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_ZF, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2796000, + canopyActivation, + 2796000, // *not* the NU6 activation height zf_addresses); consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_ZIP214_MG, - consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2796000, + canopyActivation, + 2796000, // *not* the NU6 activation height mg_addresses); - auto nu6Activation = consensus.vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight; - std::vector zcg_addresses(13, "t2HifwjUj9uyxr9bknR8LFuQbc98c3vkXtu"); + // ZIP 214 Revision 1 + // FPF uses a single address repeated 13 times, once for each funding period. + // There are 13 periods because the start height does not align with a period boundary. + std::vector fpf_addresses(13, "t2HifwjUj9uyxr9bknR8LFuQbc98c3vkXtu"); consensus.AddZIP207FundingStream( keyConstants, Consensus::FS_FPF_ZCG, nu6Activation, 3396000, - zcg_addresses); + fpf_addresses); consensus.AddZIP207LockboxStream( keyConstants, Consensus::FS_DEFERRED, diff --git a/src/clientversion.h b/src/clientversion.h index 8b5352addd9..4a98a917342 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -15,8 +15,8 @@ */ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 5 -#define CLIENT_VERSION_MINOR 10 +#define CLIENT_VERSION_MAJOR 6 +#define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_BUILD 50 diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 490d8ad95e6..f8bd2df7134 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -43,7 +43,7 @@ namespace Consensus { }, { .recipient = "Lockbox NU6", - .specification = "https://zips.z.cash/draft-nuttycom-funding-allocation", + .specification = "https://zips.z.cash/zip-0214", .valueNumerator = 12, .valueDenominator = 100, } @@ -342,16 +342,16 @@ namespace Consensus { } } - std::vector Params::GetActiveFundingStreams(int nHeight) const + std::vector> Params::GetActiveFundingStreams(int nHeight) const { - std::vector activeStreams; + std::vector> activeStreams; // Funding streams are disabled if Canopy is not active. if (NetworkUpgradeActive(nHeight, Consensus::UPGRADE_CANOPY)) { for (uint32_t idx = Consensus::FIRST_FUNDING_STREAM; idx < Consensus::MAX_FUNDING_STREAMS; idx++) { auto fs = vFundingStreams[idx]; if (fs && nHeight >= fs.value().GetStartHeight() && nHeight < fs.value().GetEndHeight()) { - activeStreams.push_back(FundingStreamInfo[idx]); + activeStreams.push_back(std::make_pair(FundingStreamInfo[idx], fs.value())); } } } diff --git a/src/consensus/params.h b/src/consensus/params.h index efcdfcaa59d..62eee52a368 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -347,7 +347,7 @@ struct Params { /** * Returns the vector of active funding streams as of the given height. */ - std::vector GetActiveFundingStreams(int nHeight) const; + std::vector> GetActiveFundingStreams(int nHeight) const; /** * Returns the vector of active funding stream elements as of the given height. diff --git a/src/deprecation.h b/src/deprecation.h index c342ff844e2..8b477dff7c1 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -14,8 +14,8 @@ // Shut down nodes running this version of code, `RELEASE_TO_DEPRECATION_WEEKS` weeks' worth // of blocks after the estimated release block height. A warning is shown during the 14 days' // worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 2625900; -static const int RELEASE_TO_DEPRECATION_WEEKS = 10; +static const int APPROX_RELEASE_HEIGHT = 2667376; +static const int RELEASE_TO_DEPRECATION_WEEKS = 16; static const int EXPECTED_BLOCKS_PER_HOUR = 3600 / Consensus::POST_BLOSSOM_POW_TARGET_SPACING; static_assert(EXPECTED_BLOCKS_PER_HOUR == 48, "The value of Consensus::POST_BLOSSOM_POW_TARGET_SPACING was chosen such that this assertion holds."); static const int ACTIVATION_TO_DEPRECATION_BLOCKS = (RELEASE_TO_DEPRECATION_WEEKS * 7 * 24 * EXPECTED_BLOCKS_PER_HOUR); diff --git a/src/main.cpp b/src/main.cpp index b15c2efc814..1fad8ee9a62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1921,7 +1921,8 @@ bool AcceptToMemoryPool( ", which is over the limit of %d. The conventional fee for this transaction is %d " + MINOR_CURRENCY_UNIT, tx.GetHash().ToString(), nSize, nModifiedFees, nModifiedFees - nFees, nUnpaidActionCount, nTxUnpaidActionLimit, tx.GetConventionalFee()); - return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "tx unpaid action limit exceeded"); + return state.DoS(0, false, REJECT_INSUFFICIENTFEE, + strprintf("tx unpaid action limit exceeded: %d action(s) exceeds limit of %d", nUnpaidActionCount, nTxUnpaidActionLimit)); } if (fRejectAbsurdFee && nFees > maxTxFee) { diff --git a/src/miner.cpp b/src/miner.cpp index 878c23a1df9..84a41a1d6dc 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -75,6 +75,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam nNewTime = std::min(nNewTime, medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP); } + // The timestamp of a given block template should not go backwards. if (nOldTime < nNewTime) pblock->nTime = nNewTime; @@ -366,7 +367,11 @@ CBlockTemplate* BlockAssembler::CreateNewBlock( if (chainparams.MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); - pblock->nTime = GetTime(); + // Setting nTime to 0 and then calling UpdateTime ensures that it is set to the + // nearest timestamp to the current time in the consensus-valid range (see #6960). + pblock->nTime = 0; + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); CCoinsViewCache view(pcoinsTip); diff --git a/src/policy/policy.h b/src/policy/policy.h index 9b988db1d27..2d2ef4d31d8 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -71,7 +71,7 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_ * set to 1000 zats, per ZIP 313. * * #6542 changed relaying policy to be more strict about enforcing minRelayTxFee. - * It also allowed `-minrelaytxfee=0`, which we are using to avoid some test + * It also allowed `-minrelaytxfee=0`, which we were using to avoid some test * breakage. But if the dust threshold rate were still set to three times the * minRelayTxFee rate, then setting `-minrelaytxfee=0` would have the side effect * of setting the dust threshold to zero, which is not intended. diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 4b133f311ec..59c36d2af63 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -968,7 +968,7 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp) UniValue lockboxstreams(UniValue::VARR); auto fsinfos = consensus.GetActiveFundingStreams(nHeight); for (int idx = 0; idx < fsinfos.size(); idx++) { - const auto& fsinfo = fsinfos[idx]; + const auto& fsinfo = fsinfos[idx].first; CAmount nStreamAmount = fsinfo.Value(nBlockSubsidy); UniValue fsobj(UniValue::VOBJ); @@ -977,8 +977,8 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp) fsobj.pushKV("value", ValueFromAmount(nStreamAmount)); fsobj.pushKV("valueZat", nStreamAmount); - auto fs = consensus.vFundingStreams[idx]; - auto recipient = fs.value().Recipient(consensus, nHeight); + auto fs = fsinfos[idx].second; + auto recipient = fs.Recipient(consensus, nHeight); examine(recipient, match { [&](const CScript& scriptPubKey) { diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 1141e7c8036..e73714b7840 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -372,18 +372,44 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // Stop here if we needed to mine more blocks. assert(nblocks == sizeof(blockinfo)/sizeof(*blockinfo)); + auto nTime = pblocktemplate->block.nTime; + delete pblocktemplate; + // Set the clock to be just ahead of the last "mined" block, to ensure we satisfy the // future timestamp soft fork rule. - auto curTime = GetTime(); - OffsetClock::SetGlobal(); - OffsetClock::Instance()->Set(std::chrono::seconds(-curTime + pblocktemplate->block.nTime)); + FixedClock::SetGlobal(); + FixedClock::Instance()->Set(std::chrono::seconds(nTime)); + // Just to make sure we can still make simple blocks + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); + BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, nTime); + + auto mtp = chainActive.Tip()->GetMedianTimePast(); delete pblocktemplate; + auto minTime = mtp + 1; + auto maxTime = mtp + MAX_FUTURE_BLOCK_TIME_MTP; - // Just to make sure we can still make simple blocks + // Set the clock to be too far ahead of the MTP, violating the future timestamp rule. + FixedClock::Instance()->Set(std::chrono::seconds(maxTime + 1)); + + // This should succeed, and nTime should be clamped to the maximum consensus-valid value. + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); + BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, maxTime); + delete pblocktemplate; + + // Set the clock to be equal to the median-time-past, violating the rule that it must + // be after the MTP. + FixedClock::Instance()->Set(std::chrono::seconds(minTime - 1)); + + // This should succeed, and nTime should be clamped to the minimum consensus-valid value. BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); + BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, minTime); delete pblocktemplate; + auto curTime = GetTime(); + OffsetClock::SetGlobal(); + OffsetClock::Instance()->Set(std::chrono::seconds(-curTime + nTime)); + TestMemPoolEntryHelper entry; entry.nFee = 0; entry.nHeight = 0; diff --git a/src/version.h b/src/version.h index 1cf9cb7711e..6c9b0d40bf9 100644 --- a/src/version.h +++ b/src/version.h @@ -10,7 +10,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170110; +static const int PROTOCOL_VERSION = 170120; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 19052d8c436..414ce0f4021 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -13,6 +13,7 @@ #include #include +#include const int MIGRATION_EXPIRY_DELTA = 450; @@ -159,13 +160,19 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } } assert(changeAddr.has_value()); - // The amount chosen *includes* the default fee for this transaction, i.e. - // the value of the Sapling output will be 0.00001 ZEC less. - builder.SetFee(LEGACY_DEFAULT_FEE); + + // The amount chosen includes the fee for this transaction, as it will be after + // adding the Sapling output. The first JoinSplit will consume two real inputs and + // each subsequent JoinSplit will consume one real input, usually (it is possible + // for the builder to use fewer JoinSplits but this only results in overestimating + // the fee). The number of Sapling outputs will be padded to 2. + auto fee = CalculateConventionalFee(2 * fromNotes.size() + 2); + builder.SetFee(fee); + builder.AddSaplingOutput( ovkForShieldingFromTaddr(seed), migrationDestAddress, - amountToSend - LEGACY_DEFAULT_FEE, + amountToSend - fee, std::nullopt); builder.SendChangeToSprout(changeAddr.value()); CTransaction tx = builder.Build().GetTxOrThrow(); @@ -176,7 +183,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { pwalletMain->AddPendingSaplingMigrationTx(tx); LogPrint("zrpcunsafe", "%s: Added pending migration transaction with txid=%s\n", getId(), tx.GetHash().ToString()); ++numTxCreated; - amountMigrated += amountToSend - LEGACY_DEFAULT_FEE; + amountMigrated += amountToSend - fee; migrationTxIds.push_back(tx.GetHash().ToString()); } while (numTxCreated < 5 && availableFunds > CENT); diff --git a/src/wallet/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp index b64f8db12d3..ecbe5a8f69a 100644 --- a/src/wallet/test/rpc_wallet_tests.cpp +++ b/src/wallet/test/rpc_wallet_tests.cpp @@ -315,8 +315,25 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) } }; + auto check_lockbox_streams = [](UniValue obj, std::vector recipients, std::vector amounts) { + size_t n = recipients.size(); + BOOST_REQUIRE_EQUAL(amounts.size(), n); + UniValue lockboxstreams = find_value(obj, "lockboxstreams"); + BOOST_CHECK_EQUAL(lockboxstreams.size(), n); + if (lockboxstreams.size() != n) return; + + for (int i = 0; i < n; i++) { + UniValue fsobj = lockboxstreams[i]; + BOOST_CHECK_EQUAL(find_value(fsobj, "recipient").get_str(), recipients[i]); + BOOST_CHECK_EQUAL(find_value(fsobj, "specification").get_str(), "https://zips.z.cash/zip-0214"); + BOOST_CHECK_EQUAL(find_value(fsobj, "value").get_real(), amounts[i]); + } + }; + bool canopyEnabled = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + bool nu6Enabled = + Params().GetConsensus().vUpgrades[Consensus::UPGRADE_NU6].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // slow start + blossom activation + (pre blossom halving - blossom activation) * 2 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1046400")); @@ -332,6 +349,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) "t3XyYW8yBFRuMnfvm5KLGFbEVz25kckZXym" }); } + BOOST_CHECK(find_value(obj, "lockboxstreams").empty()); BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2726399")); obj = retValue.get_obj(); @@ -346,9 +364,27 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) "t3XyYW8yBFRuMnfvm5KLGFbEVz25kckZXym" }); } + BOOST_CHECK(find_value(obj, "lockboxstreams").empty()); BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2726400")); obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), nu6Enabled ? 1.25 : 1.5625); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); + if (nu6Enabled) { + check_funding_streams(obj, { "Zcash Community Grants NU6" }, + { 0.125, }, + { + "t3cFfPt1Bcvgez9ZbMBFWeZsskxTkPzGCow" + }); + check_lockbox_streams(obj, { "Lockbox NU6" }, + { 0.1875, }); + } else { + BOOST_CHECK(find_value(obj, "fundingstreams").empty()); + BOOST_CHECK(find_value(obj, "lockboxstreams").empty()); + } + + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 3146400")); + obj = retValue.get_obj(); BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 1.5625); BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); BOOST_CHECK(find_value(obj, "fundingstreams").empty()); diff --git a/src/zip317.h b/src/zip317.h index 296ce1e2c8f..281c2419fb5 100644 --- a/src/zip317.h +++ b/src/zip317.h @@ -21,7 +21,7 @@ static const size_t P2PKH_STANDARD_OUTPUT_SIZE = 34; // Constants for block template construction. static const int64_t WEIGHT_RATIO_SCALE = INT64_C(10000000000000000); static const int64_t WEIGHT_RATIO_CAP = 4; -static const size_t DEFAULT_BLOCK_UNPAID_ACTION_LIMIT = 50; +static const size_t DEFAULT_BLOCK_UNPAID_ACTION_LIMIT = 0; /// Limit on the number of unpaid actions a transaction can have to be accepted to the mempool. static const size_t DEFAULT_TX_UNPAID_ACTION_LIMIT = DEFAULT_BLOCK_UNPAID_ACTION_LIMIT;