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