Repository: zcash/zcash (language: rust)

Issue:
Block template construction fails to properly clamp the block time to satisfy the "future timestamp" rule
From protocol spec [§ 7.6 Block Header Encoding and Consensus](https://zips.z.cash/protocol/protocol.pdf#blockheader):

> For each block at block height 2 or greater on Mainnet, or block height 653606 or greater on Testnet, `nTime`
**MUST** be less than or equal to the median-time-past of that block plus 90 · 60 seconds.

This rule is not correctly applied by zcashd's block template construction.

If the median-time-past is more than 90 minutes ago, then a new block with `nTime` set to the current time would violate the rule. At `miner.cpp` lines 74-76 in `UpdateTime`: https://github.com/zcash/zcash/blob/1c0c425fdea00d5c6382a11245cfc4ee7bd492cd/src/miner.cpp#L68-L79
there is code that is intended to allow recovering from that situation by clamping `nTime` to the range allowed by this consensus rule (and also by the "nTime must be greater than median-time-past" rule).

However, that code does not work as intended, because `nOldTime` is set to `pblock->nTime` which is initially set to the current time at https://github.com/zcash/zcash/blob/1c0c425fdea00d5c6382a11245cfc4ee7bd492cd/src/miner.cpp#L369

`UpdateTime` is only called to update `nTime` for an existing block template, not to set it initially. So, if `nTime` starts at a value that violates the rule, the condition `nOldTime < nNewTime` does not hold when `UpdateTime` is called, and so `nTime` remains at the invalid value rather than being set to the clamped value.

(The intent of the `if (nOldTime < nNewTime)` is to not allow `nTime` to go backwards for a given template. This would be fine by itself absent the initialization problem.)

Note that if a block has not been mined on testnet for more than 24 hours, an additional problem is that (with default options) zcashd nodes will never exit Initial Block Download, and so will not start mining. However, that can be worked around by setting the `maxtipage` config option. Once it is set, the above bug will be exposed (and it is also exposed if the median-time-past is between 90 minutes and 24 hours ago).

This is in practice a testnet-only bug, because it is vanishingly unlikely that a block would fail to be mined on mainnet for 24h.

The fix is to initialize `nTime` to 0 and then immediately call `UpdateTime`, rather than initializing it to `GetTime()`.


Discussion / hints:

Fix patch:
diff --git a/.cargo/config.toml.offline b/.cargo/config.toml.offline
index 704f9f3ea6d..8b7762d20bf 100644
--- a/.cargo/config.toml.offline
+++ b/.cargo/config.toml.offline
@@ -4,25 +4,5 @@ linker = "aarch64-linux-gnu-gcc"
 [source.crates-io]
 replace-with = "vendored-sources"
 
-[source."https://github.com/zcash/incrementalmerkletree"]
-git = "https://github.com/zcash/incrementalmerkletree"
-rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293"
-replace-with = "vendored-sources"
-
-[source."https://github.com/zcash/orchard"]
-git = "https://github.com/zcash/orchard"
-rev = "55fb089a335bbbc1cda186c706bc037073df8eb7"
-replace-with = "vendored-sources"
-
-[source."https://github.com/zcash/sapling-crypto"]
-git = "https://github.com/zcash/sapling-crypto"
-rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c"
-replace-with = "vendored-sources"
-
-[source."https://github.com/zcash/librustzcash.git"]
-git = "https://github.com/zcash/librustzcash.git"
-rev = "1410f1449100a417bfbc4f6c7167aa9808e38792"
-replace-with = "vendored-sources"
-
 [source.vendored-sources]
 # The directory for this source is set to RUST_VENDORED_SOURCES by src/Makefile.am
diff --git a/Cargo.lock b/Cargo.lock
index 4f9fe5c3067..605b9360aba 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -259,7 +259,8 @@ dependencies = [
 [[package]]
 name = "bridgetree"
 version = "0.6.0"
-source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cef977c7f8e75aa81fc589064c121ab8d32448b7939d34d58df479aa93e65ea5"
 dependencies = [
  "incrementalmerkletree",
 ]
@@ -592,7 +593,8 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 [[package]]
 name = "equihash"
 version = "0.2.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5"
 dependencies = [
  "blake2b_simd",
  "byteorder",
@@ -611,7 +613,8 @@ dependencies = [
 [[package]]
 name = "f4jumble"
 version = "0.1.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75"
 dependencies = [
  "blake2b_simd",
 ]
@@ -921,7 +924,8 @@ dependencies = [
 [[package]]
 name = "incrementalmerkletree"
 version = "0.7.0"
-source = "git+https://github.com/zcash/incrementalmerkletree?rev=ffe4234788fd22662b937ba7c6ea01535fcc1293#ffe4234788fd22662b937ba7c6ea01535fcc1293"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df"
 dependencies = [
  "either",
  "proptest",
@@ -1350,8 +1354,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
 
 [[package]]
 name = "orchard"
-version = "0.9.1"
-source = "git+https://github.com/zcash/orchard?rev=55fb089a335bbbc1cda186c706bc037073df8eb7#55fb089a335bbbc1cda186c706bc037073df8eb7"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f18e997fa121de5c73e95cdc7e8512ae43b7de38904aeea5e5713cc48f3c0ba"
 dependencies = [
  "aes",
  "bitvec",
@@ -1803,8 +1808,9 @@ dependencies = [
 
 [[package]]
 name = "sapling-crypto"
-version = "0.2.0"
-source = "git+https://github.com/zcash/sapling-crypto?rev=b1ad3694ee13a2fc5d291ad04721a6252da0993c#b1ad3694ee13a2fc5d291ad04721a6252da0993c"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfff8cfce16aeb38da50b8e2ed33c9018f30552beff2210c266662a021b17f38"
 dependencies = [
  "aes",
  "bellman",
@@ -2538,8 +2544,9 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
 
 [[package]]
 name = "zcash_address"
-version = "0.5.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ff95eac82f71286a79c750e674550d64fb2b7aadaef7b89286b2917f645457d"
 dependencies = [
  "bech32",
  "bs58",
@@ -2551,7 +2558,8 @@ dependencies = [
 [[package]]
 name = "zcash_encoding"
 version = "0.2.1"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052d8230202f0a018cd9b5d1b56b94cd25e18eccc2d8665073bcea8261ab87fc"
 dependencies = [
  "byteorder",
  "nonempty",
@@ -2560,7 +2568,8 @@ dependencies = [
 [[package]]
 name = "zcash_history"
 version = "0.4.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fde17bf53792f9c756b313730da14880257d7661b5bfc69d0571c3a7c11a76d"
 dependencies = [
  "blake2b_simd",
  "byteorder",
@@ -2582,8 +2591,9 @@ dependencies = [
 
 [[package]]
 name = "zcash_primitives"
-version = "0.17.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ab47d526d7fd6f88b3a2854ad81b54757a80c2aeadd1d8b06f690556af9743c"
 dependencies = [
  "aes",
  "bip32",
@@ -2621,8 +2631,9 @@ dependencies = [
 
 [[package]]
 name = "zcash_proofs"
-version = "0.17.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daba607872e60d91a09248d8e1ea3d6801c819fb80d67016d9de02d81323c10d"
 dependencies = [
  "bellman",
  "blake2b_simd",
@@ -2643,8 +2654,9 @@ dependencies = [
 
 [[package]]
 name = "zcash_protocol"
-version = "0.3.0"
-source = "git+https://github.com/zcash/librustzcash.git?rev=1410f1449100a417bfbc4f6c7167aa9808e38792#1410f1449100a417bfbc4f6c7167aa9808e38792"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bc22b9155b2c7eb20105cd06de170d188c1bc86489b92aa3fda7b8da8d96acf"
 dependencies = [
  "document-features",
  "incrementalmerkletree",
diff --git a/Cargo.toml b/Cargo.toml
index 2f4b524b7ca..a6ca7f7ef17 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -50,8 +50,8 @@ libc = "0.2"
 jubjub = "0.10"
 memuse = "0.2"
 nonempty = "0.7"
-orchard = "0.9"
-sapling = { package = "sapling-crypto", version = "0.2", features = ["temporary-zcashd"] }
+orchard = "0.10"
+sapling = { package = "sapling-crypto", version = "0.3", features = ["temporary-zcashd"] }
 secp256k1 = "0.27"
 subtle = "2.2"
 rand_core = "0.6"
@@ -59,13 +59,13 @@ redjubjub = "0.7"
 tracing = "0.1"
 tracing-core = "0.1"
 tracing-appender = "0.2"
-zcash_address = "0.5"
+zcash_address = "0.6"
 zcash_encoding = "0.2.1"
 zcash_history = "0.4"
 zcash_note_encryption = "0.4"
-zcash_primitives = { version = "0.17", features = ["temporary-zcashd", "transparent-inputs"] }
-zcash_proofs = { version = "0.17", features = ["directories"] }
-zcash_protocol = { version = "0.3", features = ["local-consensus"] }
+zcash_primitives = { version = "0.19", features = ["temporary-zcashd", "transparent-inputs"] }
+zcash_proofs = { version = "0.19", features = ["directories"] }
+zcash_protocol = { version = "0.4", features = ["local-consensus"] }
 ed25519-zebra = "4"
 zeroize = "1.4.2"
 wagyu-zcash-parameters = "0.2"
@@ -100,7 +100,7 @@ time = { version = "0.3", features = ["formatting", "macros"] }
 [dev-dependencies]
 incrementalmerkletree = { version = "0.7", features = ["test-dependencies"] }
 proptest = "1.0.0"
-zcash_primitives = { version = "0.17", features = ["temporary-zcashd", "transparent-inputs", "test-dependencies"] }
+zcash_primitives = { version = "0.19", features = ["temporary-zcashd", "transparent-inputs", "test-dependencies"] }
 
 [dependencies.tracing-subscriber]
 version = "0.3"
@@ -111,16 +111,3 @@ features = ["ansi", "env-filter", "fmt", "time"]
 lto = 'thin'
 panic = 'abort'
 codegen-units = 1
-
-[patch.crates-io]
-bridgetree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" }
-incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" }
-orchard = { git = "https://github.com/zcash/orchard", rev = "55fb089a335bbbc1cda186c706bc037073df8eb7" }
-sapling-crypto = { git = "https://github.com/zcash/sapling-crypto", rev = "b1ad3694ee13a2fc5d291ad04721a6252da0993c" }
-equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
-zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "1410f1449100a417bfbc4f6c7167aa9808e38792" }
diff --git a/README.md b/README.md
index 6be5f24eb2d..66c3eb9e9de 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-Zcash 6.0.0-rc1
+Zcash 6.0.0
 <img align="right" width="120" height="80" src="doc/imgs/logo.png">
 ===========
 
diff --git a/configure.ac b/configure.ac
index 93d06d2f30b..3a45d46757f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ AC_PREREQ([2.60])
 define(_CLIENT_VERSION_MAJOR, 6)
 define(_CLIENT_VERSION_MINOR, 0)
 define(_CLIENT_VERSION_REVISION, 0)
-define(_CLIENT_VERSION_BUILD, 25)
+define(_CLIENT_VERSION_BUILD, 50)
 define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
 define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
 define(_CLIENT_VERSION_IS_RELEASE, true)
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index d1f72b85f40..8ea0a87060e 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,3 +1,9 @@
+zcash (6.0.0) stable; urgency=high
+
+  * 6.0.0 release.
+
+ -- Electric Coin Company <team@electriccoin.co>  Wed, 02 Oct 2024 20:45:09 +0000
+
 zcash (6.0.0~rc1) stable; urgency=medium
 
   * 6.0.0-rc1 release.
diff --git a/contrib/gitian-descriptors/gitian-linux-parallel.yml b/contrib/gitian-descriptors/gitian-linux-parallel.yml
index d1ca5d0eeb6..ced83a7a1c5 100644
--- a/contrib/gitian-descriptors/gitian-linux-parallel.yml
+++ b/contrib/gitian-descriptors/gitian-linux-parallel.yml
@@ -1,5 +1,5 @@
 ---
-name: "zcash-6.0.0-rc1"
+name: "zcash-6.0.0"
 enable_cache: true
 distro: "debian"
 suites:
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index abaec372f96..e0ab81a022e 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -1,5 +1,5 @@
 ---
-name: "zcash-6.0.0-rc1"
+name: "zcash-6.0.0"
 enable_cache: true
 distro: "debian"
 suites:
diff --git a/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 9d938a53d96..52f62788950 100644
--- a/doc/book/src/user/release-support.md
+++ b/doc/book/src/user/release-support.md
@@ -45,4 +45,5 @@ time, and may shift due to changes in network solution power.
 | 5.10.0-rc1 | 2024-08-22 | 2700600 | 2024-10-31 |
 | 5.10.0 | 2024-08-27 | 2706540 | 2024-11-05 |
 | 6.0.0-rc1 | 2024-09-27 | 2710272 | 2024-11-08 |
+| 6.0.0 | 2024-10-02 | 2796400 | 2025-01-22 |
 <!-- RELEASE_SCRIPT_END_MARKER -->
diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1
index 0962d4c3ca8..d9878345d00 100644
--- a/doc/man/zcash-cli.1
+++ b/doc/man/zcash-cli.1
@@ -1,9 +1,9 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.1.
-.TH ZCASH-CLI "1" "September 2024" "zcash-cli v6.0.0-rc1" "User Commands"
+.TH ZCASH-CLI "1" "October 2024" "zcash-cli v6.0.0" "User Commands"
 .SH NAME
-zcash-cli \- manual page for zcash-cli v6.0.0-rc1
+zcash-cli \- manual page for zcash-cli v6.0.0
 .SH DESCRIPTION
-Zcash RPC client version v6.0.0\-rc1
+Zcash RPC client version v6.0.0
 .PP
 In order to ensure you are adequately protecting your privacy when using Zcash,
 please see <https://z.cash/support/security/>.
diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1
index a905807c015..cffaa517bc7 100644
--- a/doc/man/zcash-tx.1
+++ b/doc/man/zcash-tx.1
@@ -1,9 +1,9 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.1.
-.TH ZCASH-TX "1" "September 2024" "zcash-tx v6.0.0-rc1" "User Commands"
+.TH ZCASH-TX "1" "October 2024" "zcash-tx v6.0.0" "User Commands"
 .SH NAME
-zcash-tx \- manual page for zcash-tx v6.0.0-rc1
+zcash-tx \- manual page for zcash-tx v6.0.0
 .SH DESCRIPTION
-Zcash zcash\-tx utility version v6.0.0\-rc1
+Zcash zcash\-tx utility version v6.0.0
 .SS "Usage:"
 .TP
 zcash\-tx [options] <hex\-tx> [commands]
diff --git a/doc/man/zcashd-wallet-tool.1 b/doc/man/zcashd-wallet-tool.1
index b6184533de8..54314e1d750 100644
--- a/doc/man/zcashd-wallet-tool.1
+++ b/doc/man/zcashd-wallet-tool.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.1.
-.TH ZCASHD-WALLET-TOOL "1" "September 2024" "zcashd-wallet-tool v6.0.0-rc1" "User Commands"
+.TH ZCASHD-WALLET-TOOL "1" "October 2024" "zcashd-wallet-tool v6.0.0" "User Commands"
 .SH NAME
-zcashd-wallet-tool \- manual page for zcashd-wallet-tool v6.0.0-rc1
+zcashd-wallet-tool \- manual page for zcashd-wallet-tool v6.0.0
 .SH SYNOPSIS
 .B zcashd-wallet-tool
 [\fI\,OPTIONS\/\fR]
diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1
index dc509792cf9..9da9ecaf635 100644
--- a/doc/man/zcashd.1
+++ b/doc/man/zcashd.1
@@ -1,9 +1,9 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.1.
-.TH ZCASHD "1" "September 2024" "zcashd v6.0.0-rc1" "User Commands"
+.TH ZCASHD "1" "October 2024" "zcashd v6.0.0" "User Commands"
 .SH NAME
-zcashd \- manual page for zcashd v6.0.0-rc1
+zcashd \- manual page for zcashd v6.0.0
 .SH DESCRIPTION
-Zcash Daemon version v6.0.0\-rc1
+Zcash Daemon version v6.0.0
 .PP
 In order to ensure you are adequately protecting your privacy when using Zcash,
 please see <https://z.cash/support/security/>.
@@ -484,7 +484,7 @@ Maximum size of data in data carrier transactions we relay and mine
 \fB\-txunpaidactionlimit=\fR<n>
 .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<n>
 .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.md b/doc/release-notes.md
index 93368dacc84..a29094b5174 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -4,18 +4,3 @@ release-notes at release time)
 Notable changes
 ===============
 
-Mining
-------
-
-- The default setting of `-blockunpaidactionlimit` is now zero, which has
-  the effect of no longer allowing "unpaid actions" in [block production].
-  This adapts to current network conditions. If you have overridden this
-  setting as a miner, we recommend removing the override. This configuration
-  option may be removed entirely in a future release.
-
-[block production]: https://zips.z.cash/zip-0317#block-production
-
-Platform Support
-----------------
-
-- Windows builds have been fixed.
diff --git a/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/supply-chain/audits.toml b/qa/supply-chain/audits.toml
index 56b015f4722..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,13 +3092,13 @@ end = "2024-09-21"
 criteria = "safe-to-deploy"
 user-id = 169181 # Kris Nuttycombe (nuttycom)
 start = "2023-02-28"
-end = "2024-09-21"
+end = "2025-10-02"
 
 [[trusted.incrementalmerkletree-testing]]
 criteria = "safe-to-deploy"
 user-id = 169181 # Kris Nuttycombe (nuttycom)
-start = "2024-09-27"
-end = "2025-09-27"
+start = "2024-09-25"
+end = "2025-10-02"
 
 [[trusted.orchard]]
 criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
@@ -3112,12 +3112,24 @@ user-id = 1244 # ebfull
 start = "2022-10-19"
 end = "2024-09-21"
 
+[[trusted.orchard]]
+criteria = "safe-to-deploy"
+user-id = 169181 # Kris Nuttycombe (nuttycom)
+start = "2024-08-12"
+end = "2025-10-02"
+
 [[trusted.sapling-crypto]]
 criteria = ["safe-to-deploy", "crypto-reviewed", "license-reviewed"]
 user-id = 6289 # Jack Grigg (str4d)
 start = "2024-01-26"
 end = "2025-03-18"
 
+[[trusted.sapling-crypto]]
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+user-id = 169181 # Kris Nuttycombe (nuttycom)
+start = "2024-08-12"
+end = "2025-10-02"
+
 [[trusted.windows-sys]]
 criteria = "safe-to-deploy"
 user-id = 64539 # Kenny Kerr (kennykerr)
@@ -3238,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)
@@ -3250,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 3e06744ca14..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,15 +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-27"
+when = "2024-09-25"
+user-id = 169181
+user-login = "nuttycom"
+user-name = "Kris Nuttycombe"
+
+[[publisher.orchard]]
+version = "0.10.0"
+when = "2024-10-02"
+user-id = 169181
+user-login = "nuttycom"
+user-name = "Kris Nuttycombe"
+
+[[publisher.sapling-crypto]]
+version = "0.3.0"
+when = "2024-10-02"
 user-id = 169181
 user-login = "nuttycom"
 user-name = "Kris Nuttycombe"
@@ -140,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"
@@ -161,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"
@@ -1677,3 +1697,21 @@ who = "Jack Grigg <jack@electriccoin.co>"
 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 <kris@nutty.land>"
+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 <kris@nutty.land>"
+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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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 f4702c1d3fa..4a98a917342 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -18,7 +18,7 @@
 #define CLIENT_VERSION_MAJOR 6
 #define CLIENT_VERSION_MINOR 0
 #define CLIENT_VERSION_REVISION 0
-#define CLIENT_VERSION_BUILD 25
+#define CLIENT_VERSION_BUILD 50
 
 //! Set to true for release, false for prerelease or test build
 #define CLIENT_VERSION_IS_RELEASE true
diff --git a/src/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<FSInfo> Params::GetActiveFundingStreams(int nHeight) const
+    std::vector<std::pair<FSInfo, FundingStream>> Params::GetActiveFundingStreams(int nHeight) const
     {
-        std::vector<FSInfo> activeStreams;
+        std::vector<std::pair<FSInfo, FundingStream>> 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<FSInfo> GetActiveFundingStreams(int nHeight) const;
+    std::vector<std::pair<FSInfo, FundingStream>> 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 6c41e29d3a1..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 = 2661888;
-static const int RELEASE_TO_DEPRECATION_WEEKS = 6;
+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/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/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/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;


Test patch:
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/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<std::string> recipients, std::vector<double> 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());