From 4aebdeb362c43e815b91810dc1021fe7f8565480 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:11:44 +0000 Subject: [PATCH 01/29] Migrate to latest revision of Zcash Rust crates --- .cargo/config.toml.offline | 20 ++++++++++++++ Cargo.lock | 53 ++++++++++++++++++------------------ Cargo.toml | 19 +++++++++++-- qa/supply-chain/audits.toml | 6 ++++ qa/supply-chain/imports.lock | 7 +++++ 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/.cargo/config.toml.offline b/.cargo/config.toml.offline index 8b7762d20bf..704f9f3ea6d 100644 --- a/.cargo/config.toml.offline +++ b/.cargo/config.toml.offline @@ -4,5 +4,25 @@ linker = "aarch64-linux-gnu-gcc" [source.crates-io] replace-with = "vendored-sources" +[source."https://github.com/zcash/incrementalmerkletree"] +git = "https://github.com/zcash/incrementalmerkletree" +rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" +replace-with = "vendored-sources" + +[source."https://github.com/zcash/orchard"] +git = "https://github.com/zcash/orchard" +rev = "55fb089a335bbbc1cda186c706bc037073df8eb7" +replace-with = "vendored-sources" + +[source."https://github.com/zcash/sapling-crypto"] +git = "https://github.com/zcash/sapling-crypto" +rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c" +replace-with = "vendored-sources" + +[source."https://github.com/zcash/librustzcash.git"] +git = "https://github.com/zcash/librustzcash.git" +rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" +replace-with = "vendored-sources" + [source.vendored-sources] # The directory for this source is set to RUST_VENDORED_SOURCES by src/Makefile.am diff --git a/Cargo.lock b/Cargo.lock index d14eea0073f..4f9fe5c3067 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,9 +258,8 @@ dependencies = [ [[package]] name = "bridgetree" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62227647af796dd9f1637da0392676a2e200973b817b082fc9be89bf93ddd74" +version = "0.6.0" +source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293" dependencies = [ "incrementalmerkletree", ] @@ -593,8 +592,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equihash" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "blake2b_simd", "byteorder", @@ -613,8 +611,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "blake2b_simd", ] @@ -923,9 +920,8 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75346da3bd8e3d8891d02508245ed2df34447ca6637e343829f8d08986e9cde2" +version = "0.7.0" +source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293" dependencies = [ "either", "proptest", @@ -933,6 +929,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 +1350,8 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc7bde644aeb980be296cd908c6650894dc8541deb56f9f5294c52ed7ca568f" +version = "0.9.1" +source = "git+https://github.com/zcash/orchard?rev=55fb089a335bbbc1cda186c706bc037073df8eb7#55fb089a335bbbc1cda186c706bc037073df8eb7" dependencies = [ "aes", "bitvec", @@ -1799,8 +1804,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e379398fffad84e49f9a45a05635fc004f66086e65942dbf4eb95332c26d2a" +source = "git+https://github.com/zcash/sapling-crypto?rev=b1ad3694ee13a2fc5d291ad04721a6252da0993c#b1ad3694ee13a2fc5d291ad04721a6252da0993c" dependencies = [ "aes", "bellman", @@ -2535,8 +2539,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bccd6cefb76f87b6d15a9e7b02b6c0515648c6de8e806c4e2d6f0f6ae640c5" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "bech32", "bs58", @@ -2548,8 +2551,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052d8230202f0a018cd9b5d1b56b94cd25e18eccc2d8665073bcea8261ab87fc" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "byteorder", "nonempty", @@ -2558,8 +2560,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fde17bf53792f9c756b313730da14880257d7661b5bfc69d0571c3a7c11a76d" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "blake2b_simd", "byteorder", @@ -2582,8 +2583,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d87ab6a55591a8cf1866749fdc739ae1bbd06e6cec07ab0bbe5d57ee3390eb2" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "aes", "bip32", @@ -2622,8 +2622,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9fc0032b3d90f000f50dba7a996ad6556b7dba5b5145f93ab67b6eb74d3a48" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "bellman", "blake2b_simd", @@ -2645,11 +2644,11 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1ff002bd41ba76b42d42a02ee11de06790b7fdbc904bdea4486b9a93b2a5e4" +source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" dependencies = [ "document-features", "incrementalmerkletree", + "incrementalmerkletree-testing", "memuse", "proptest", ] diff --git a/Cargo.toml b/Cargo.toml index b1c17b25cb7..2f4b524b7ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,13 +39,13 @@ 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" @@ -98,7 +98,7 @@ 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"] } @@ -111,3 +111,16 @@ features = ["ansi", "env-filter", "fmt", "time"] lto = 'thin' panic = 'abort' codegen-units = 1 + +[patch.crates-io] +bridgetree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } +incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } +orchard = { git = "https://github.com/zcash/orchard", rev = "55fb089a335bbbc1cda186c706bc037073df8eb7" } +sapling-crypto = { git = "https://github.com/zcash/sapling-crypto", rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c" } +equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } diff --git a/qa/supply-chain/audits.toml b/qa/supply-chain/audits.toml index 683f8c90e76..56b015f4722 100644 --- a/qa/supply-chain/audits.toml +++ b/qa/supply-chain/audits.toml @@ -3094,6 +3094,12 @@ user-id = 169181 # Kris Nuttycombe (nuttycom) start = "2023-02-28" end = "2024-09-21" +[[trusted.incrementalmerkletree-testing]] +criteria = "safe-to-deploy" +user-id = 169181 # Kris Nuttycombe (nuttycom) +start = "2024-09-27" +end = "2025-09-27" + [[trusted.orchard]] criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"] user-id = 6289 # Jack Grigg (str4d) diff --git a/qa/supply-chain/imports.lock b/qa/supply-chain/imports.lock index 1bd8f97dd7d..3e06744ca14 100644 --- a/qa/supply-chain/imports.lock +++ b/qa/supply-chain/imports.lock @@ -55,6 +55,13 @@ user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" +[[publisher.incrementalmerkletree-testing]] +version = "0.1.0" +when = "2024-09-27" +user-id = 169181 +user-login = "nuttycom" +user-name = "Kris Nuttycombe" + [[publisher.unicode-normalization]] version = "0.1.23" when = "2024-02-20" From f15b744ed6ba8fdcc1067d96299f3fc57d0507f3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:24:11 +0000 Subject: [PATCH 02/29] depends: native_cmake 3.30.4 --- depends/packages/native_cmake.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 3c79887dc2be432da22e86c00f6e3c3516ac3377 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:26:11 +0000 Subject: [PATCH 03/29] Update release notes --- doc/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..6fd5c2dd79f 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,4 @@ release-notes at release time) Notable changes =============== +- Windows builds have been fixed. From 157c27cbe82e263a315c32ffa8e42e37e2262b9f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:30:37 +0000 Subject: [PATCH 04/29] Decrease support window to 6 weeks for 6.0.0-rc1 --- src/deprecation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deprecation.h b/src/deprecation.h index c342ff844e2..ea011942fea 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -15,7 +15,7 @@ // 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 RELEASE_TO_DEPRECATION_WEEKS = 6; 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); From 757b127cd8d5512fbcef08dce395c165578f1fb3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:34:34 +0000 Subject: [PATCH 05/29] make-release.py: Versioning changes for 6.0.0-rc1. --- README.md | 2 +- configure.ac | 6 +++--- contrib/gitian-descriptors/gitian-linux-parallel.yml | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 6 +++--- src/deprecation.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 72101ec4ea5..6be5f24eb2d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 5.10.0 +Zcash 6.0.0-rc1 =========== diff --git a/configure.ac b/configure.ac index e5ee383a0d4..93d06d2f30b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ 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(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux-parallel.yml b/contrib/gitian-descriptors/gitian-linux-parallel.yml index 78eb0a1e0d3..d1ca5d0eeb6 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-rc1" enable_cache: true distro: "debian" suites: diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 044b3e33a5c..abaec372f96 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-rc1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 8b5352addd9..f4702c1d3fa 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -15,10 +15,10 @@ */ //! 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 +#define CLIENT_VERSION_BUILD 25 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index ea011942fea..6c41e29d3a1 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -14,7 +14,7 @@ // 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 APPROX_RELEASE_HEIGHT = 2661888; static const int RELEASE_TO_DEPRECATION_WEEKS = 6; 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."); From 7c7de391d9957523755e5e37cb4617f7234563d4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:51:33 +0000 Subject: [PATCH 06/29] make-release.py: Updated manpages for 6.0.0-rc1. --- doc/man/zcash-cli.1 | 8 ++++---- doc/man/zcash-tx.1 | 8 ++++---- doc/man/zcashd-wallet-tool.1 | 6 +++--- doc/man/zcashd.1 | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 0d1aac63f6c..0962d4c3ca8 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" "September 2024" "zcash-cli v6.0.0-rc1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v5.10.0 +zcash-cli \- manual page for zcash-cli v6.0.0-rc1 .SH DESCRIPTION -Zcash RPC client version v5.10.0 +Zcash RPC client version v6.0.0\-rc1 .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..a905807c015 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" "September 2024" "zcash-tx v6.0.0-rc1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v5.10.0 +zcash-tx \- manual page for zcash-tx v6.0.0-rc1 .SH DESCRIPTION -Zcash zcash\-tx utility version v5.10.0 +Zcash zcash\-tx utility version v6.0.0\-rc1 .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..b6184533de8 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" "September 2024" "zcashd-wallet-tool v6.0.0-rc1" "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-rc1 .SH SYNOPSIS .B zcashd-wallet-tool [\fI\,OPTIONS\/\fR] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 79a9ea0a446..dc509792cf9 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" "September 2024" "zcashd v6.0.0-rc1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v5.10.0 +zcashd \- manual page for zcashd v6.0.0-rc1 .SH DESCRIPTION -Zcash Daemon version v5.10.0 +Zcash Daemon version v6.0.0\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From bc163daf2f178e2ba3cc98ef68669aa01f1aa5f1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:51:34 +0000 Subject: [PATCH 07/29] make-release.py: Updated release notes and changelog for 6.0.0-rc1. --- contrib/debian/changelog | 6 ++++ doc/release-notes/release-notes-6.0.0-rc1.md | 37 ++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 doc/release-notes/release-notes-6.0.0-rc1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 346f7a36baf..d1f72b85f40 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +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/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) + From c3c5fd5ab1ef5fd4284671b67fd5dd55ccc1c354 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2024 19:51:34 +0000 Subject: [PATCH 08/29] make-release.py: Updated book for 6.0.0-rc1. --- doc/book/src/user/release-support.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/book/src/user/release-support.md b/doc/book/src/user/release-support.md index 4b95d87fe6e..9d938a53d96 100644 --- a/doc/book/src/user/release-support.md +++ b/doc/book/src/user/release-support.md @@ -42,8 +42,7 @@ 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 | From 535f434032c620ed9ba0d80158689c7339346eac Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 2 Oct 2024 03:52:07 +0100 Subject: [PATCH 09/29] Make DEFAULT_BLOCK_UNPAID_ACTION_LIMIT zero. fixes #6899 (see that issue for rationale) Signed-off-by: Daira-Emma Hopwood --- doc/release-notes.md | 14 ++++++++++++++ src/zip317.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6fd5c2dd79f..93368dacc84 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,4 +4,18 @@ release-notes at release time) Notable changes =============== +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. 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; From e379dc03416bf4e39af1935532425e4fd14f217b Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Tue, 6 Aug 2024 04:01:25 +0100 Subject: [PATCH 10/29] Add more detail to the "tx unpaid action limit exceeded" message. Signed-off-by: Daira-Emma Hopwood --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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) { From 34c0c125de7219b654b09131f262aaac173a5478 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Mon, 12 Aug 2024 16:42:56 +0100 Subject: [PATCH 11/29] Use at least the ZIP 317 fee for Sprout->Sapling migration. Because of excessive complexity in the Sprout JoinSplit construction algorithm, we might not be able to compute the exact ZIP 317 fee, since we essentially need to predict how many JoinSplits the algorithm will use. So, we use a conservative upper bound to compute the fee. The difference betweeen that upper bound and the actual number of JoinSplits might leak some information. Signed-off-by: Daira-Emma Hopwood --- .../asyncrpcoperation_saplingmigration.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) 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); From 8b436e8f1fcc9aa0990f56aa31c2a28555c6a370 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Thu, 26 Sep 2024 14:05:57 +0100 Subject: [PATCH 12/29] Repair the RPC tests. Co-authored-by: Jack Grigg Signed-off-by: Daira-Emma Hopwood --- qa/rpc-tests/addressindex.py | 7 +- qa/rpc-tests/feature_zip239.py | 6 +- qa/rpc-tests/finalorchardroot.py | 32 +- qa/rpc-tests/finalsaplingroot.py | 31 +- qa/rpc-tests/getblocktemplate.py | 13 +- qa/rpc-tests/invalidtxrequest.py | 11 +- qa/rpc-tests/mempool_limit.py | 29 +- qa/rpc-tests/mempool_nu_activation.py | 59 ++-- qa/rpc-tests/mempool_packages.py | 4 +- qa/rpc-tests/mempool_reorg.py | 19 +- qa/rpc-tests/mempool_resurrect_test.py | 11 +- qa/rpc-tests/mempool_spendcoinbase.py | 9 +- qa/rpc-tests/mempool_tx_expiry.py | 31 +- qa/rpc-tests/mergetoaddress_helper.py | 103 +++--- qa/rpc-tests/mergetoaddress_mixednotes.py | 19 +- qa/rpc-tests/merkle_blocks.py | 23 +- qa/rpc-tests/mining_shielded_coinbase.py | 36 +- qa/rpc-tests/orchard_reorg.py | 16 +- qa/rpc-tests/p2p_txexpiringsoon.py | 9 +- qa/rpc-tests/prioritisetransaction.py | 95 ++++-- qa/rpc-tests/regtest_signrawtransaction.py | 6 +- qa/rpc-tests/remove_sprout_shielding.py | 14 +- qa/rpc-tests/shorter_block_times.py | 15 +- qa/rpc-tests/show_help.py | 6 +- qa/rpc-tests/signrawtransaction_offline.py | 7 +- qa/rpc-tests/sprout_sapling_migration.py | 10 +- qa/rpc-tests/test_framework/blocktools.py | 6 +- qa/rpc-tests/test_framework/util.py | 4 +- qa/rpc-tests/test_framework/zip317.py | 7 +- qa/rpc-tests/turnstile.py | 20 +- qa/rpc-tests/txn_doublespend.py | 20 +- qa/rpc-tests/wallet.py | 101 +++--- qa/rpc-tests/wallet_1941.py | 15 +- qa/rpc-tests/wallet_accounts.py | 42 ++- qa/rpc-tests/wallet_anchorfork.py | 18 +- qa/rpc-tests/wallet_changeaddresses.py | 22 +- qa/rpc-tests/wallet_changeindicator.py | 31 +- qa/rpc-tests/wallet_doublespend.py | 52 +-- qa/rpc-tests/wallet_isfromme.py | 51 ++- qa/rpc-tests/wallet_listnotes.py | 20 +- qa/rpc-tests/wallet_listreceived.py | 5 +- qa/rpc-tests/wallet_listunspent.py | 60 ++-- qa/rpc-tests/wallet_nullifiers.py | 15 +- qa/rpc-tests/wallet_orchard.py | 77 +++-- qa/rpc-tests/wallet_orchard_change.py | 37 +- qa/rpc-tests/wallet_orchard_init.py | 28 +- qa/rpc-tests/wallet_orchard_persistence.py | 28 +- qa/rpc-tests/wallet_orchard_reindex.py | 13 +- qa/rpc-tests/wallet_overwintertx.py | 69 ++-- qa/rpc-tests/wallet_persistence.py | 59 ++-- qa/rpc-tests/wallet_sapling.py | 70 ++-- qa/rpc-tests/wallet_sendmany_any_taddr.py | 73 ++-- qa/rpc-tests/wallet_shieldcoinbase.py | 63 ++-- qa/rpc-tests/wallet_shieldingcoinbase.py | 70 ++-- qa/rpc-tests/wallet_treestate.py | 29 +- qa/rpc-tests/wallet_unified_change.py | 48 +-- qa/rpc-tests/wallet_z_sendmany.py | 377 ++++++++++++--------- qa/rpc-tests/zkey_import_export.py | 57 ++-- src/policy/policy.h | 2 +- 59 files changed, 1196 insertions(+), 1014 deletions(-) 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..d7908a0d7c7 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 `null` because it calculates a fee + # that is too low. If we passed `fee` in here instead, it would succeed. + # https://github.com/zcash/zcash/issues/6956 + fee = conventional_fee(4) + myopid = self.nodes[0].z_sendmany(ua0, recipients, 1, ZIP_317_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/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/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. From dd791388c75d7ccce9ba8d0ed47dee953f8bc452 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 2 Oct 2024 03:42:34 +0100 Subject: [PATCH 13/29] Add a regression test for the ZIP 317 default fee bug (#6956), and make the tests pass for now. Signed-off-by: Daira-Emma Hopwood --- qa/pull-tester/rpc-tests.py | 4 +- qa/rpc-tests/wallet_orchard_change.py | 6 +- qa/rpc-tests/wallet_zip317_default.py | 97 +++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) create mode 100755 qa/rpc-tests/wallet_zip317_default.py 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/wallet_orchard_change.py b/qa/rpc-tests/wallet_orchard_change.py index d7908a0d7c7..a7208c8e132 100755 --- a/qa/rpc-tests/wallet_orchard_change.py +++ b/qa/rpc-tests/wallet_orchard_change.py @@ -71,11 +71,11 @@ def run_test(self): ua1 = self.nodes[1].z_getaddressforaccount(acct1, ['orchard'])['address'] recipients = [{"address": ua1, "amount": Decimal('1')}] - # TODO The z_sendmany call fails when passed `null` because it calculates a fee - # that is too low. If we passed `fee` in here instead, it would succeed. + # 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, ZIP_317_FEE, 'AllowRevealedAmounts') + 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() 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() From 1951ec76d064742c5b610ab2e24479076d43ae28 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 2 Oct 2024 14:12:41 +0100 Subject: [PATCH 14/29] Code of Conduct: update email addresses and remove Sean as a contact. Signed-off-by: Daira-Emma Hopwood --- code_of_conduct.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code_of_conduct.md b/code_of_conduct.md index 07e751de779..cd71b69146d 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -47,13 +47,12 @@ 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) This Code of Conduct is adapted from the [Contributor Covenant][homepage], From 4e44eadbdb02407fddd17739c8be1cc6da494f64 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 2 Oct 2024 18:17:26 +0100 Subject: [PATCH 15/29] Code of Conduct: add Kris and Str4d as contacts. Signed-off-by: Daira-Emma Hopwood --- code_of_conduct.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code_of_conduct.md b/code_of_conduct.md index cd71b69146d..0661386014c 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -53,6 +53,8 @@ If you wish to contact specific maintainers directly, the following have made themselves available for conduct issues: - 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], From f5245c7092ffcca0eeb5efdd8a24cc2bb386aec3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:19:45 +0000 Subject: [PATCH 16/29] qa: Add latest Clang release to postponed updates --- qa/zcash/postponed-updates.txt | 2 ++ 1 file changed, 2 insertions(+) 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 From fd47b5af5227d3cddfee2118b7df1fa7c4442a1f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:26:29 +0000 Subject: [PATCH 17/29] Migrate to librustzcash crates revision right before NU6 mainnet height This gets the other side-effects of the recent changes out of the way, and then in the commit where we set the mainnet activation height in `zcashd`, we can do so uniformly across the stack. --- .cargo/config.toml.offline | 17 +---------------- Cargo.lock | 32 ++++++++++++++++++-------------- Cargo.toml | 22 +++++++++------------- qa/supply-chain/audits.toml | 20 ++++++++++++++++---- qa/supply-chain/config.toml | 8 -------- qa/supply-chain/imports.lock | 30 +++++++++++++++++++++++++++++- 6 files changed, 73 insertions(+), 56 deletions(-) diff --git a/.cargo/config.toml.offline b/.cargo/config.toml.offline index 704f9f3ea6d..103a23f9b94 100644 --- a/.cargo/config.toml.offline +++ b/.cargo/config.toml.offline @@ -4,24 +4,9 @@ linker = "aarch64-linux-gnu-gcc" [source.crates-io] replace-with = "vendored-sources" -[source."https://github.com/zcash/incrementalmerkletree"] -git = "https://github.com/zcash/incrementalmerkletree" -rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" -replace-with = "vendored-sources" - -[source."https://github.com/zcash/orchard"] -git = "https://github.com/zcash/orchard" -rev = "55fb089a335bbbc1cda186c706bc037073df8eb7" -replace-with = "vendored-sources" - -[source."https://github.com/zcash/sapling-crypto"] -git = "https://github.com/zcash/sapling-crypto" -rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c" -replace-with = "vendored-sources" - [source."https://github.com/zcash/librustzcash.git"] git = "https://github.com/zcash/librustzcash.git" -rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" +rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" replace-with = "vendored-sources" [source.vendored-sources] diff --git a/Cargo.lock b/Cargo.lock index 4f9fe5c3067..7ae294afebf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,7 +259,8 @@ dependencies = [ [[package]] name = "bridgetree" version = "0.6.0" -source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef977c7f8e75aa81fc589064c121ab8d32448b7939d34d58df479aa93e65ea5" dependencies = [ "incrementalmerkletree", ] @@ -592,7 +593,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "blake2b_simd", "byteorder", @@ -611,7 +612,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "blake2b_simd", ] @@ -921,7 +922,8 @@ dependencies = [ [[package]] name = "incrementalmerkletree" version = "0.7.0" -source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df" dependencies = [ "either", "proptest", @@ -1350,8 +1352,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" -version = "0.9.1" -source = "git+https://github.com/zcash/orchard?rev=55fb089a335bbbc1cda186c706bc037073df8eb7#55fb089a335bbbc1cda186c706bc037073df8eb7" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f18e997fa121de5c73e95cdc7e8512ae43b7de38904aeea5e5713cc48f3c0ba" dependencies = [ "aes", "bitvec", @@ -1803,8 +1806,9 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.2.0" -source = "git+https://github.com/zcash/sapling-crypto?rev=b1ad3694ee13a2fc5d291ad04721a6252da0993c#b1ad3694ee13a2fc5d291ad04721a6252da0993c" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfff8cfce16aeb38da50b8e2ed33c9018f30552beff2210c266662a021b17f38" dependencies = [ "aes", "bellman", @@ -2539,7 +2543,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "bech32", "bs58", @@ -2551,7 +2555,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.1" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "byteorder", "nonempty", @@ -2560,7 +2564,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "blake2b_simd", "byteorder", @@ -2583,7 +2587,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.17.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "aes", "bip32", @@ -2622,7 +2626,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.17.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "bellman", "blake2b_simd", @@ -2644,7 +2648,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.3.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792" +source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" dependencies = [ "document-features", "incrementalmerkletree", diff --git a/Cargo.toml b/Cargo.toml index 2f4b524b7ca..ff86dd92203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,8 +50,8 @@ 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" @@ -113,14 +113,10 @@ panic = 'abort' codegen-units = 1 [patch.crates-io] -bridgetree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } -incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } -orchard = { git = "https://github.com/zcash/orchard", rev = "55fb089a335bbbc1cda186c706bc037073df8eb7" } -sapling-crypto = { git = "https://github.com/zcash/sapling-crypto", rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c" } -equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } -zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" } +equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } +zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } diff --git a/qa/supply-chain/audits.toml b/qa/supply-chain/audits.toml index 56b015f4722..cdc23f55728 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,13 +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-27" -end = "2025-09-27" +start = "2024-09-25" +end = "2025-10-02" [[trusted.orchard]] criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"] @@ -3112,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) diff --git a/qa/supply-chain/config.toml b/qa/supply-chain/config.toml index 2346b168bdc..c5b1ef6643d 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" diff --git a/qa/supply-chain/imports.lock b/qa/supply-chain/imports.lock index 3e06744ca14..bfebf885bfa 100644 --- a/qa/supply-chain/imports.lock +++ b/qa/supply-chain/imports.lock @@ -8,6 +8,13 @@ user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" +[[publisher.bridgetree]] +version = "0.6.0" +when = "2024-09-25" +user-id = 169181 +user-login = "nuttycom" +user-name = "Kris Nuttycombe" + [[publisher.bumpalo]] version = "3.16.0" when = "2024-04-08" @@ -55,9 +62,30 @@ user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" +[[publisher.incrementalmerkletree]] +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-27" +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" From bf3b8d7e16d091423274a3adcb59d53937a66cb8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:28:04 +0000 Subject: [PATCH 18/29] Set support window back to the usual 16 weeks --- src/deprecation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deprecation.h b/src/deprecation.h index 6c41e29d3a1..8cf10aa705d 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -15,7 +15,7 @@ // 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 = 2661888; -static const int RELEASE_TO_DEPRECATION_WEEKS = 6; +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); From 79a72d79a5dc11f8ec4d33e2991f1280c75ddd58 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:37:29 +0000 Subject: [PATCH 19/29] Update release notes for 6.0.0 --- doc/release-notes.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 93368dacc84..82ef7ebc66f 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,24 @@ release-notes at release time) 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 ------ From b7708cc68e1b5b20372bb069b41b13d3892f9b77 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:41:53 +0000 Subject: [PATCH 20/29] make-release.py: Versioning changes for 6.0.0. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux-parallel.yml | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6be5f24eb2d..66c3eb9e9de 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 6.0.0-rc1 +Zcash 6.0.0 =========== diff --git a/configure.ac b/configure.ac index 93d06d2f30b..3a45d46757f 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 6) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 25) +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))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux-parallel.yml b/contrib/gitian-descriptors/gitian-linux-parallel.yml index d1ca5d0eeb6..ced83a7a1c5 100644 --- a/contrib/gitian-descriptors/gitian-linux-parallel.yml +++ b/contrib/gitian-descriptors/gitian-linux-parallel.yml @@ -1,5 +1,5 @@ --- -name: "zcash-6.0.0-rc1" +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 abaec372f96..e0ab81a022e 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-6.0.0-rc1" +name: "zcash-6.0.0" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index f4702c1d3fa..4a98a917342 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 6 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 25 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 8cf10aa705d..8b477dff7c1 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -14,7 +14,7 @@ // 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 = 2661888; +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."); From 4e1e6fe164b1ed9dc39571869365a748061002b8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:45:08 +0000 Subject: [PATCH 21/29] make-release.py: Updated manpages for 6.0.0. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd-wallet-tool.1 | 4 ++-- doc/man/zcashd.1 | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 0962d4c3ca8..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.1. -.TH ZCASH-CLI "1" "September 2024" "zcash-cli v6.0.0-rc1" "User Commands" +.TH ZCASH-CLI "1" "October 2024" "zcash-cli v6.0.0" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v6.0.0-rc1 +zcash-cli \- manual page for zcash-cli v6.0.0 .SH DESCRIPTION -Zcash RPC client version v6.0.0\-rc1 +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 a905807c015..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.1. -.TH ZCASH-TX "1" "September 2024" "zcash-tx v6.0.0-rc1" "User Commands" +.TH ZCASH-TX "1" "October 2024" "zcash-tx v6.0.0" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v6.0.0-rc1 +zcash-tx \- manual page for zcash-tx v6.0.0 .SH DESCRIPTION -Zcash zcash\-tx utility version v6.0.0\-rc1 +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 b6184533de8..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.1. -.TH ZCASHD-WALLET-TOOL "1" "September 2024" "zcashd-wallet-tool v6.0.0-rc1" "User Commands" +.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 v6.0.0-rc1 +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 dc509792cf9..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.1. -.TH ZCASHD "1" "September 2024" "zcashd v6.0.0-rc1" "User Commands" +.TH ZCASHD "1" "October 2024" "zcashd v6.0.0" "User Commands" .SH NAME -zcashd \- manual page for zcashd v6.0.0-rc1 +zcashd \- manual page for zcashd v6.0.0 .SH DESCRIPTION -Zcash Daemon version v6.0.0\-rc1 +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 From 337afb9d0257315601ea3dbe6fb91f7e90962a1f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:45:09 +0000 Subject: [PATCH 22/29] make-release.py: Updated release notes and changelog for 6.0.0. --- contrib/debian/changelog | 6 ++ doc/authors.md | 8 +-- doc/release-notes.md | 33 ---------- doc/release-notes/release-notes-6.0.0.md | 84 ++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 37 deletions(-) create mode 100644 doc/release-notes/release-notes-6.0.0.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index d1f72b85f40..866cbe62a71 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (6.0.0) stable; urgency=medium + + * 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. 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/release-notes.md b/doc/release-notes.md index 82ef7ebc66f..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,36 +4,3 @@ release-notes at release time) 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. 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) + From 09cae52fc0607802413d180087b25ee2ec81734e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:45:09 +0000 Subject: [PATCH 23/29] make-release.py: Updated book for 6.0.0. --- doc/book/src/user/release-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/book/src/user/release-support.md b/doc/book/src/user/release-support.md index 9d938a53d96..52f62788950 100644 --- a/doc/book/src/user/release-support.md +++ b/doc/book/src/user/release-support.md @@ -45,4 +45,5 @@ time, and may shift due to changes in network solution power. | 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 | From 74ff943c400484e839762118f3b43eaa97fcc879 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 2 Oct 2024 20:48:07 +0000 Subject: [PATCH 24/29] debian: Set urgency of 6.0.0 release to `high` --- contrib/debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 866cbe62a71..8ea0a87060e 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,4 +1,4 @@ -zcash (6.0.0) stable; urgency=medium +zcash (6.0.0) stable; urgency=high * 6.0.0 release. From a0602ebfb765a965acd8de0b012da28f257a6918 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 2 Oct 2024 21:28:00 +0000 Subject: [PATCH 25/29] Changes necessary for NU6 funding streams and activation height. Co-authored-by: Jack Grigg Signed-off-by: Daira-Emma Hopwood --- .cargo/config.toml.offline | 5 --- Cargo.lock | 32 ++++++++++------ Cargo.toml | 19 +++------- qa/supply-chain/audits.toml | 12 ++++++ qa/supply-chain/config.toml | 8 ---- qa/supply-chain/imports.lock | 72 ++++++++++++++++++++---------------- src/chainparams.cpp | 53 ++++++++++++++++++++------ src/version.h | 2 +- 8 files changed, 121 insertions(+), 82 deletions(-) diff --git a/.cargo/config.toml.offline b/.cargo/config.toml.offline index 103a23f9b94..8b7762d20bf 100644 --- a/.cargo/config.toml.offline +++ b/.cargo/config.toml.offline @@ -4,10 +4,5 @@ linker = "aarch64-linux-gnu-gcc" [source.crates-io] replace-with = "vendored-sources" -[source."https://github.com/zcash/librustzcash.git"] -git = "https://github.com/zcash/librustzcash.git" -rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" -replace-with = "vendored-sources" - [source.vendored-sources] # The directory for this source is set to RUST_VENDORED_SOURCES by src/Makefile.am diff --git a/Cargo.lock b/Cargo.lock index 7ae294afebf..605b9360aba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -593,7 +593,8 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" dependencies = [ "blake2b_simd", "byteorder", @@ -612,7 +613,8 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" dependencies = [ "blake2b_simd", ] @@ -2542,8 +2544,9 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" -version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ff95eac82f71286a79c750e674550d64fb2b7aadaef7b89286b2917f645457d" dependencies = [ "bech32", "bs58", @@ -2555,7 +2558,8 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.1" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052d8230202f0a018cd9b5d1b56b94cd25e18eccc2d8665073bcea8261ab87fc" dependencies = [ "byteorder", "nonempty", @@ -2564,7 +2568,8 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fde17bf53792f9c756b313730da14880257d7661b5bfc69d0571c3a7c11a76d" dependencies = [ "blake2b_simd", "byteorder", @@ -2586,8 +2591,9 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.17.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab47d526d7fd6f88b3a2854ad81b54757a80c2aeadd1d8b06f690556af9743c" dependencies = [ "aes", "bip32", @@ -2625,8 +2631,9 @@ dependencies = [ [[package]] name = "zcash_proofs" -version = "0.17.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daba607872e60d91a09248d8e1ea3d6801c819fb80d67016d9de02d81323c10d" dependencies = [ "bellman", "blake2b_simd", @@ -2647,8 +2654,9 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.3.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=9ef4117504a7aa51447ffa8691c7d86c5a1dcd05#9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bc22b9155b2c7eb20105cd06de170d188c1bc86489b92aa3fda7b8da8d96acf" dependencies = [ "document-features", "incrementalmerkletree", diff --git a/Cargo.toml b/Cargo.toml index ff86dd92203..a6ca7f7ef17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" @@ -100,7 +100,7 @@ time = { version = "0.3", features = ["formatting", "macros"] } [dev-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" @@ -111,12 +111,3 @@ features = ["ansi", "env-filter", "fmt", "time"] lto = 'thin' panic = 'abort' codegen-units = 1 - -[patch.crates-io] -equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } -zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "9ef4117504a7aa51447ffa8691c7d86c5a1dcd05" } diff --git a/qa/supply-chain/audits.toml b/qa/supply-chain/audits.toml index cdc23f55728..1b1a7c9f7d4 100644 --- a/qa/supply-chain/audits.toml +++ b/qa/supply-chain/audits.toml @@ -3250,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) @@ -3262,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 c5b1ef6643d..41aaf9eae09 100644 --- a/qa/supply-chain/config.toml +++ b/qa/supply-chain/config.toml @@ -562,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" @@ -630,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 bfebf885bfa..efc9dcdc94a 100644 --- a/qa/supply-chain/imports.lock +++ b/qa/supply-chain/imports.lock @@ -1,13 +1,6 @@ # cargo-vet imports lock -[[publisher.bridgetree]] -version = "0.5.0" -when = "2024-08-12" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" - [[publisher.bridgetree]] version = "0.6.0" when = "2024-09-25" @@ -55,13 +48,6 @@ when = "2023-03-22" user-id = 1244 user-login = "ebfull" -[[publisher.incrementalmerkletree]] -version = "0.6.0" -when = "2024-08-12" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" - [[publisher.incrementalmerkletree]] version = "0.7.0" when = "2024-09-25" @@ -168,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" @@ -189,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" @@ -1705,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/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/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; From 9831458a4af73f781194f6634720e89ade4da7f4 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Fri, 4 Oct 2024 03:19:41 +0100 Subject: [PATCH 26/29] Ensure that the "future timestamp" rule is correctly applied by block template construction. fixes #6960 Signed-off-by: Daira-Emma Hopwood --- src/miner.cpp | 7 ++++++- src/test/miner_tests.cpp | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) 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/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; From 6c765107f1798a9e92834bab90b26bcf8351db5f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 4 Oct 2024 08:28:54 +0000 Subject: [PATCH 27/29] rpc: Fetch correct funding streams in `getblocksubsidy` The previous logic was indexing into the global funding streams list with the local index into the active funding streams. This worked fine for the first funding stream period, but once a funding stream ended and another was enabled, the indices no longer matched. We now return the `FundingStream` from `GetActiveFundingStreams`, as the only user of that method is `getblocksubsidy`. --- src/consensus/params.cpp | 6 +++--- src/consensus/params.h | 2 +- src/rpc/mining.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 490d8ad95e6..c311ffdb07a 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -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/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) { From bd17de8b42e489fa172e330459206bc558b1f725 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 4 Oct 2024 08:48:06 +0000 Subject: [PATCH 28/29] test: Update `getblocksubsidy` test with NU6 mainnet funding streams --- src/wallet/test/rpc_wallet_tests.cpp | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) 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()); From 97bba691ab59f2904163dffbf22204f753f6b94d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 4 Oct 2024 08:48:57 +0000 Subject: [PATCH 29/29] Fix specification URL for NU6 lockbox --- src/consensus/params.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index c311ffdb07a..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, }