Repository: zcash/zcash (language: rust)

Issue:
Bundle all ≥2.0 zkSNARK params except the Sprout-on-Groth proving params into the binary
Currently users need to download the zkSNARK parameters with `zcash-fetch-params` prior to using their node the first time. This is an annoying hurdle.

What if the params came with the binary distribution? Well, they are large, so that may be cumbersome. However, the size of the parameters may be dominated by the Sprout proving key which is only necessary for users who need to send _from_ Sprout addresses. New users shouldn't ever need to send from Sprout addresses and old users have probably already fetched the parameters.

So, if all the parameters aside from the Sprout-on-groth proving key were small enough, we could bake them into the binary, and leave `zcash-fetch-params` to retrieve only the Sprout-on-groth spending key. Then the wallet could detect when sending from Sprout if the proving parameters are missing and request to the user to fetch them. Most users would never hit that case, presumably, and so most users would have an improved onboarding experience with one fewer steps and startup delay.
Make PARAMS_DIR of fetch-params.sh configurable from CLI
When using fetch-params.sh the download location is **hardcoded** and cannot be changed without modifying the script. Please allow the download location of the parameters to be changed by flag to script, or via env variable. Can't the script simply check first if the env $PARAMS_DIR is set and if not, then use the defaults?


Discussion / hints:
Does it really matter for someone who is about to sync ~23GB (and growing) of blockchain data if he needs to download a few hundred MBs more?

Also, concept NACK for having a fat binary.

I would rather have the option to store the parameters (or any kind of data for that matter) in the volume of my choice.
@rex4539 The main benefit here has nothing to do with bandwidth; it's eliminating a step from zcashd installation, that has to be triggered manually and that can go wrong. (One way in which it can go wrong is that the download is blocked by state-level network censorship, which is quite common for an important subset of our users -- even though other network access needed by zcashd isn't being blocked.)

We can and will address the bandwidth and time requirements of syncing separately.
Is there a reason why the `zcash-fetch-params` script is a separate process and not built in to zcashd? Would it would to add this as a step in initialization prior to downloading blocks?
It's mainly because the original Sprout parameters were so large.
We have also previously discussed other distribution mechanisms that leverage existing channels. For example, we could package the parameters in Debian packages, and then not only do we get automatic distribution of them at install time, but we also get de-duplication across multiple applications that depend on the same parameters.
I now prefer the #4491 approach for a variety of reasons.
I think this is a good idea. However, I think it should be done with/after #4491 (which folds fetch-params into zcashd, rather than a separate step to run). That way we don’t have to use an environment var to keep in sync between the apps, but can implement this as a `zcashd` config file entry and/or command-line option.

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 577f7d9a21f..5648f6ee852 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1102,6 +1102,7 @@ dependencies = [
  "tracing-core",
  "tracing-subscriber",
  "uint",
+ "wagyu-zcash-parameters",
  "zcash_address",
  "zcash_encoding",
  "zcash_history",
@@ -2305,6 +2306,56 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "wagyu-zcash-parameters"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61c904628658374e651288f000934c33ef738b2d8b3e65d4100b70b395dbe2bb"
+dependencies = [
+ "wagyu-zcash-parameters-1",
+ "wagyu-zcash-parameters-2",
+ "wagyu-zcash-parameters-3",
+ "wagyu-zcash-parameters-4",
+ "wagyu-zcash-parameters-5",
+ "wagyu-zcash-parameters-6",
+]
+
+[[package]]
+name = "wagyu-zcash-parameters-1"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bf2e21bb027d3f8428c60d6a720b54a08bf6ce4e6f834ef8e0d38bb5695da8"
+
+[[package]]
+name = "wagyu-zcash-parameters-2"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a616ab2e51e74cc48995d476e94de810fb16fc73815f390bf2941b046cc9ba2c"
+
+[[package]]
+name = "wagyu-zcash-parameters-3"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14da1e2e958ff93c0830ee68e91884069253bf3462a67831b02b367be75d6147"
+
+[[package]]
+name = "wagyu-zcash-parameters-4"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f058aeef03a2070e8666ffb5d1057d8bb10313b204a254a6e6103eb958e9a6d6"
+
+[[package]]
+name = "wagyu-zcash-parameters-5"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ffe916b30e608c032ae1b734f02574a3e12ec19ab5cc5562208d679efe4969d"
+
+[[package]]
+name = "wagyu-zcash-parameters-6"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7b6d5a78adc3e8f198e9cd730f219a695431467f7ec29dcfc63ade885feebe1"
+
 [[package]]
 name = "wait-timeout"
 version = "0.2.0"
diff --git a/Cargo.toml b/Cargo.toml
index 0406bda9ae3..41cb73ca7f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,6 +66,7 @@ zcash_primitives = { version = "0.12", features = ["temporary-zcashd", "transpar
 zcash_proofs = { version = "0.12", features = ["directories"] }
 ed25519-zebra = "4"
 zeroize = "1.4.2"
+wagyu-zcash-parameters = "0.2"
 
 # Rust/C++ interop
 # The version needs to match depends/packages/native_cxxbridge.mk
diff --git a/doc/release-notes.md b/doc/release-notes.md
index a29094b5174..652628dd3b4 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -4,3 +4,23 @@ release-notes at release time)
 Notable changes
 ===============
 
+Deprecation of `fetch-params.sh`
+--------------------------------
+
+The `fetch-params.sh` script (also `zcash-fetch-params`) is now deprecated. The
+zcashd binary now bundles zk-SNARK parameters directly and so parameters do not
+need to be downloaded or stored separately. The script will now do nothing but
+state that it is deprecated; it will be removed in a future release.
+
+Previously, parameters were stored by default in these locations:
+
+* `~/.zcash-params` (on Linux); or
+* `~/Library/Application Support/ZcashParams` (on Mac); or
+* `C:\Users\Username\AppData\Roaming\ZcashParams` (on Windows)
+
+Unless you need to generate transactions using the deprecated Sprout shielded
+pool, you can delete the parameter files stored in these directories to save
+space as they are no longer read or used by zcashd. If you do wish to use the
+Sprout pool, you will need the `sprout-groth16.params` file in the
+aforementioned directory. This file is currently available for download
+[here](https://download.z.cash/downloads/sprout-groth16.params).
diff --git a/qa/supply-chain/audits.toml b/qa/supply-chain/audits.toml
index 3395adcfaf0..2ead14cf95f 100644
--- a/qa/supply-chain/audits.toml
+++ b/qa/supply-chain/audits.toml
@@ -1580,6 +1580,41 @@ criteria = "safe-to-deploy"
 delta = "0.4.1 -> 0.5.0"
 notes = "I checked correctness of to_blocks which uses unsafe code in a safe function."
 
+[[audits.wagyu-zcash-parameters]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-1]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-2]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-3]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-4]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-5]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
+[[audits.wagyu-zcash-parameters-6]]
+who = "Sean Bowe <ewillbefull@gmail.com>"
+criteria = ["safe-to-deploy", "crypto-reviewed"]
+version = "0.2.0"
+
 [[audits.want]]
 who = "Jack Grigg <jack@electriccoin.co>"
 criteria = "safe-to-deploy"
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index dc87d20ef66..b7b4e1e5bfb 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -23,22 +23,14 @@ main(int argc, char** argv)
     SetupEnvironment();
     fPrintToDebugLog = false; // don't want to write to debug log file
 
-    fs::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
-    fs::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
     fs::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
 
     static_assert(
         sizeof(fs::path::value_type) == sizeof(codeunit),
         "librustzcash not configured correctly");
-    auto sapling_spend_str = sapling_spend.native();
-    auto sapling_output_str = sapling_output.native();
     auto sprout_groth16_str = sprout_groth16.native();
 
     librustzcash_init_zksnark_params(
-        reinterpret_cast<const codeunit*>(sapling_spend_str.c_str()),
-        sapling_spend_str.length(),
-        reinterpret_cast<const codeunit*>(sapling_output_str.c_str()),
-        sapling_output_str.length(),
         reinterpret_cast<const codeunit*>(sprout_groth16_str.c_str()),
         sprout_groth16_str.length(),
         true
diff --git a/src/init.cpp b/src/init.cpp
index 6204922dfb9..d246f67fac8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -850,42 +850,19 @@ static void ZC_LoadParams(
     struct timeval tv_start, tv_end;
     float elapsed;
 
-    fs::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
-    fs::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
     fs::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
-
-    if (!(
-        fs::exists(sapling_spend) &&
-        fs::exists(sapling_output) &&
-        fs::exists(sprout_groth16)
-    )) {
-        uiInterface.ThreadSafeMessageBox(strprintf(
-            _("Cannot find the Zcash network parameters in the following directory:\n"
-              "%s\n"
-              "Please run 'zcash-fetch-params' or './zcutil/fetch-params.sh' and then restart."),
-                ZC_GetParamsDir()),
-            "", CClientUIInterface::MSG_ERROR);
-        StartShutdown();
-        return;
-    }
-
     static_assert(
         sizeof(fs::path::value_type) == sizeof(codeunit),
         "librustzcash not configured correctly");
-    auto sapling_spend_str = sapling_spend.native();
-    auto sapling_output_str = sapling_output.native();
     auto sprout_groth16_str = sprout_groth16.native();
 
-    LogPrintf("Loading Sapling (Spend) parameters from %s\n", sapling_spend.string().c_str());
-    LogPrintf("Loading Sapling (Output) parameters from %s\n", sapling_output.string().c_str());
-    LogPrintf("Loading Sapling (Sprout Groth16) parameters from %s\n", sprout_groth16.string().c_str());
+    LogPrintf("Sprout parameters will be fetched from %s if needed\n", sprout_groth16.string().c_str());
+    LogPrintf("Sapling parameters are bundled in this binary\n");
+    LogPrintf("Orchard parameters are generated deterministically\n");
+
     gettimeofday(&tv_start, 0);
 
     librustzcash_init_zksnark_params(
-        reinterpret_cast<const codeunit*>(sapling_spend_str.c_str()),
-        sapling_spend_str.length(),
-        reinterpret_cast<const codeunit*>(sapling_output_str.c_str()),
-        sapling_output_str.length(),
         reinterpret_cast<const codeunit*>(sprout_groth16_str.c_str()),
         sprout_groth16_str.length(),
         true
diff --git a/src/rust/include/librustzcash.h b/src/rust/include/librustzcash.h
index 1e208cb0e12..88149628a0a 100644
--- a/src/rust/include/librustzcash.h
+++ b/src/rust/include/librustzcash.h
@@ -30,10 +30,6 @@ extern "C" {
     /// Loads the zk-SNARK parameters into memory and saves
     /// paths as necessary. Only called once.
     void librustzcash_init_zksnark_params(
-        const codeunit* spend_path,
-        size_t spend_path_len,
-        const codeunit* output_path,
-        size_t output_path_len,
         const codeunit* sprout_path,
         size_t sprout_path_len,
         bool load_proving_keys
diff --git a/src/rust/src/rustzcash.rs b/src/rust/src/rustzcash.rs
index 070e8cafe18..edad4e0c6ec 100644
--- a/src/rust/src/rustzcash.rs
+++ b/src/rust/src/rustzcash.rs
@@ -57,7 +57,7 @@ use zcash_primitives::{
     },
     zip32::{self, sapling_address, sapling_derive_internal_fvk, sapling_find_address},
 };
-use zcash_proofs::{load_parameters, sprout};
+use zcash_proofs::sprout;
 
 mod blake2b;
 mod ed25519;
@@ -133,12 +133,6 @@ fn fixed_scalar_mult(from: &[u8; 32], p_g: &jubjub::SubgroupPoint) -> jubjub::Su
 /// be present even if there are no shielded components to verify.
 #[no_mangle]
 pub extern "C" fn librustzcash_init_zksnark_params(
-    #[cfg(not(target_os = "windows"))] spend_path: *const u8,
-    #[cfg(target_os = "windows")] spend_path: *const u16,
-    spend_path_len: usize,
-    #[cfg(not(target_os = "windows"))] output_path: *const u8,
-    #[cfg(target_os = "windows")] output_path: *const u16,
-    output_path_len: usize,
     #[cfg(not(target_os = "windows"))] sprout_path: *const u8,
     #[cfg(target_os = "windows")] sprout_path: *const u16,
     sprout_path_len: usize,
@@ -146,45 +140,42 @@ pub extern "C" fn librustzcash_init_zksnark_params(
 ) {
     PROOF_PARAMETERS_LOADED.call_once(|| {
         #[cfg(not(target_os = "windows"))]
-        let (spend_path, output_path, sprout_path) = {
-            (
-                OsStr::from_bytes(unsafe { slice::from_raw_parts(spend_path, spend_path_len) }),
-                OsStr::from_bytes(unsafe { slice::from_raw_parts(output_path, output_path_len) }),
-                if sprout_path.is_null() {
-                    None
-                } else {
-                    Some(OsStr::from_bytes(unsafe {
-                        slice::from_raw_parts(sprout_path, sprout_path_len)
-                    }))
-                },
-            )
+        let sprout_path = if sprout_path.is_null() {
+            None
+        } else {
+            Some(OsStr::from_bytes(unsafe {
+                slice::from_raw_parts(sprout_path, sprout_path_len)
+            }))
         };
 
         #[cfg(target_os = "windows")]
-        let (spend_path, output_path, sprout_path) = {
-            (
-                OsString::from_wide(unsafe { slice::from_raw_parts(spend_path, spend_path_len) }),
-                OsString::from_wide(unsafe { slice::from_raw_parts(output_path, output_path_len) }),
-                if sprout_path.is_null() {
-                    None
-                } else {
-                    Some(OsString::from_wide(unsafe {
-                        slice::from_raw_parts(sprout_path, sprout_path_len)
-                    }))
-                },
-            )
+        let sprout_path = if sprout_path.is_null() {
+            None
+        } else {
+            Some(OsString::from_wide(unsafe {
+                slice::from_raw_parts(sprout_path, sprout_path_len)
+            }))
         };
 
-        let (spend_path, output_path, sprout_path) = (
-            Path::new(&spend_path),
-            Path::new(&output_path),
-            sprout_path.as_ref().map(Path::new),
-        );
+        let sprout_path = sprout_path.as_ref().map(Path::new);
+
+        let sprout_vk = {
+            use bellman::groth16::{prepare_verifying_key, VerifyingKey};
+            let sprout_vk_bytes = include_bytes!("sprout-groth16.vk");
+            let vk = VerifyingKey::<Bls12>::read(&sprout_vk_bytes[..])
+                .expect("should be able to parse Sprout verification key");
+            prepare_verifying_key(&vk)
+        };
 
         // Load params
-        let params = load_parameters(spend_path, output_path, sprout_path);
-        let sapling_spend_params = params.spend_params;
-        let sapling_output_params = params.output_params;
+        let (sapling_spend_params, sapling_output_params) = {
+            let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters();
+            let spend_params = Parameters::<Bls12>::read(&spend_buf[..], false)
+                .expect("couldn't deserialize Sapling spend parameters");
+            let output_params = Parameters::<Bls12>::read(&output_buf[..], false)
+                .expect("couldn't deserialize Sapling spend parameters");
+            (spend_params, output_params)
+        };
 
         // We need to clone these because we aren't necessarily storing the proving
         // parameters in memory.
@@ -205,7 +196,7 @@ pub extern "C" fn librustzcash_init_zksnark_params(
 
             SAPLING_SPEND_VK = Some(sapling_spend_vk);
             SAPLING_OUTPUT_VK = Some(sapling_output_vk);
-            SPROUT_GROTH16_VK = params.sprout_vk;
+            SPROUT_GROTH16_VK = Some(sprout_vk);
 
             ORCHARD_PK = orchard_pk;
             ORCHARD_VK = Some(orchard_vk);
@@ -515,19 +506,51 @@ pub extern "C" fn librustzcash_sprout_prove(
     vpub_old: u64,
     vpub_new: u64,
 ) {
-    // Load parameters from disk
-    let sprout_fs =
-        File::open(unsafe { &SPROUT_GROTH16_PARAMS_PATH }.as_ref().expect(
-            "Parameters not loaded: SPROUT_GROTH16_PARAMS_PATH should have been initialized",
-        ))
-        .expect("couldn't load Sprout groth16 parameters file");
-
-    let mut sprout_fs = BufReader::with_capacity(1024 * 1024, sprout_fs);
+    let params = {
+        use std::io::Read;
 
-    let params = Parameters::read(&mut sprout_fs, false)
-        .expect("couldn't deserialize Sprout JoinSplit parameters file");
+        // Load parameters from disk
+        let sprout_path = unsafe { &SPROUT_GROTH16_PARAMS_PATH }.as_ref().expect(
+            "Parameters not loaded: SPROUT_GROTH16_PARAMS_PATH should have been initialized",
+        );
+        const HOW_TO_FIX: &str = "
+Please download this file from https://download.z.cash/downloads/sprout-groth16.params
+and put it at ";
+        let sprout_fs = File::open(sprout_path).unwrap_or_else(|err| {
+            panic!(
+                "Couldn't load Sprout Groth16 parameters file: {}{}{}",
+                err,
+                HOW_TO_FIX,
+                &sprout_path.to_string_lossy()
+            )
+        });
+
+        let mut sprout_fs = BufReader::with_capacity(1024 * 1024, sprout_fs);
+
+        let mut sprout_params_file = vec![];
+        sprout_fs
+            .read_to_end(&mut sprout_params_file)
+            .unwrap_or_else(|err| {
+                panic!(
+                    "Couldn't read Sprout Groth16 parameters file: {}{}{}",
+                    err,
+                    HOW_TO_FIX,
+                    &sprout_path.to_string_lossy()
+                )
+            });
+
+        let hash = blake2b_simd::Params::new()
+            .hash_length(64)
+            .hash(&sprout_params_file);
+
+        // b2sum sprout-groth16.params
+        if hash.as_bytes() != hex::decode("e9b238411bd6c0ec4791e9d04245ec350c9c5744f5610dfcce4365d5ca49dfefd5054e371842b3f88fa1b9d7e8e075249b3ebabd167fa8b0f3161292d36c180a").unwrap().as_slice() {
+            panic!("Hash of Sprout Groth16 parameters file is incorrect.{}{}", HOW_TO_FIX, &sprout_path.to_string_lossy());
+        }
 
-    drop(sprout_fs);
+        Parameters::read(&sprout_params_file[..], false)
+            .expect("Couldn't deserialize Sprout Groth16 parameters file")
+    };
 
     let proof = sprout::create_proof(
         unsafe { *phi },
diff --git a/src/rust/src/sprout-groth16.vk b/src/rust/src/sprout-groth16.vk
new file mode 100644
index 00000000000..60f6ee96e05
Binary files /dev/null and b/src/rust/src/sprout-groth16.vk differ
diff --git a/zcutil/fetch-params.sh b/zcutil/fetch-params.sh
index f17114bd45d..25a1546e58e 100755
--- a/zcutil/fetch-params.sh
+++ b/zcutil/fetch-params.sh
@@ -3,18 +3,6 @@
 export LC_ALL=C
 set -eu
 
-SCRIPT_NAME=$(basename $0)
-
-if [[ -z "${XDG_CACHE_HOME:+x}" ]]; then
-    XDG_CACHE_HOME="${HOME}/.cache"
-fi
-
-# We don’t care too much about most of the properties of `XDG_RUNTIME_DIR` in
-# this script, so we just fall back to `XDG_CACHE_HOME`.
-if [[ -z "${XDG_RUNTIME_DIR:+x}" ]]; then
-    XDG_RUNTIME_DIR="${XDG_CACHE_HOME}";
-fi
-
 uname_S=$(uname -s 2>/dev/null || echo not)
 
 if [ "$uname_S" = "Darwin" ]; then
@@ -23,269 +11,18 @@ else
     PARAMS_DIR="$HOME/.zcash-params"
 fi
 
-# Commented out because these are unused; see below.
-#SPROUT_PKEY_NAME='sprout-proving.key'
-#SPROUT_VKEY_NAME='sprout-verifying.key'
-SAPLING_SPEND_NAME='sapling-spend.params'
-SAPLING_OUTPUT_NAME='sapling-output.params'
-SAPLING_SPROUT_GROTH16_NAME='sprout-groth16.params'
-DOWNLOAD_URL="${ALTERNATIVE_DOWNLOAD_URL:-https://download.z.cash/downloads}"
-IPFS_HASH="/ipfs/QmXRHVGLQBiKwvNq7c2vPxAKz1zRVmMYbmt7G5TQss7tY7"
-
-SHA256CMD="$(command -v sha256sum || echo shasum)"
-SHA256ARGS="$(command -v sha256sum >/dev/null || echo '-a 256')"
-
-WGETCMD="$(command -v wget || echo '')"
-IPFSCMD="$(command -v ipfs || echo '')"
-CURLCMD="$(command -v curl || echo '')"
-
-# fetch methods can be disabled with ZC_DISABLE_SOMETHING=1
-ZC_DISABLE_WGET="${ZC_DISABLE_WGET:-}"
-ZC_DISABLE_IPFS="${ZC_DISABLE_IPFS:-}"
-ZC_DISABLE_CURL="${ZC_DISABLE_CURL:-}"
-
-LOCK_DIR="${XDG_RUNTIME_DIR}/zcash"
-mkdir -p "${LOCK_DIR}"
-LOCKFILE="${LOCK_DIR}/fetch-params.lock"
-
-fetch_wget() {
-    if [ -z "$WGETCMD" ] || [ -n "$ZC_DISABLE_WGET" ]; then
-        return 1
-    fi
-
-    cat <<EOF
-
-Retrieving (wget): $DOWNLOAD_URL/$1
-EOF
-
-    wget \
-        --progress=dot:giga \
-        --output-document="$2" \
-        --continue \
-        --retry-connrefused --waitretry=3 --timeout=30 \
-        "$DOWNLOAD_URL/$1"
-}
-
-fetch_ipfs() {
-    if [ -z "$IPFSCMD" ] || [ -n "$ZC_DISABLE_IPFS" ]; then
-        return 1
-    fi
+cat <<EOF
 
-    cat <<EOF
+This script is no longer needed for users of zcashd. Proving system
+parameters now only need to be downloaded in order to spend Sprout funds.
+Parameters for other pools are bundled with the zcashd binary or generated
+when it is run, and do not need to be downloaded or stored separately.
+This script is deprecated and will be removed in a future release.
 
-Retrieving (ipfs): $IPFS_HASH/$1
-EOF
-
-    ipfs get --output "$2" "$IPFS_HASH/$1"
-}
-
-fetch_curl() {
-    if [ -z "$CURLCMD" ] || [ -n "$ZC_DISABLE_CURL" ]; then
-        return 1
-    fi
-
-    cat <<EOF
+If you need to spend Sprout funds, download the Sprout parameter file from
+https://download.z.cash/downloads/sprout-groth16.params and put it at
+$PARAMS_DIR/sprout-groth16.params
 
-Retrieving (curl): $DOWNLOAD_URL/$1
 EOF
 
-    curl \
-        --output "$2" \
-        -# -L -C - \
-        "$DOWNLOAD_URL/$1"
-
-}
-
-fetch_failure() {
-    cat >&2 <<EOF
-
-Failed to fetch the Zcash zkSNARK parameters!
-Try installing one of the following programs and make sure you're online:
-
- * ipfs
- * wget
- * curl
-
-EOF
-    exit 1
-}
-
-fetch_params() {
-    # We only set these variables inside this function,
-    # and unset them at the end of the function.
-    filename="$1"
-    output="$2"
-    dlname="${output}.dl"
-    expectedhash="$3"
-
-    if ! [ -f "$output" ]
-    then
-        for i in 1 2
-        do
-            for method in wget ipfs curl failure; do
-                if "fetch_$method" "${filename}.part.${i}" "${dlname}.part.${i}"; then
-                    echo "Download of part ${i} successful!"
-                    break
-                fi
-            done
-        done
-
-        for i in 1 2
-        do
-            if ! [ -f "${dlname}.part.${i}" ]
-            then
-                fetch_failure
-            fi
-        done
-
-        cat "${dlname}.part.1" "${dlname}.part.2" > "${dlname}"
-        rm "${dlname}.part.1" "${dlname}.part.2"
-
-        set +e
-        "$SHA256CMD" $SHA256ARGS -c <<EOF
-$expectedhash  $dlname
-EOF
-
-        # Check the exit code of the shasum command:
-        CHECKSUM_RESULT=$?
-        set -e
-        if [ $CHECKSUM_RESULT -eq 0 ]; then
-            mv -v "$dlname" "$output"
-        else
-            echo "Failed to verify parameter checksums!" >&2
-            exit 1
-        fi
-    fi
-
-    unset -v filename
-    unset -v output
-    unset -v dlname
-    unset -v expectedhash
-}
-
-check_and_fetch_params() {
-    # We only set these variables inside this function,
-    # and unset them at the end of the function.
-    filename="$1"
-    output="$2"
-    expectedhash="$3"
-
-    if ! [ -f "$output" ]
-    then
-        fetch_params "$filename" "$output" "$expectedhash"
-    else
-        # The file in question exists, so we verify its checksum.
-        # If it's not valid, we delete it and fetch it
-        set +e
-        "$SHA256CMD" $SHA256ARGS -c <<EOF
-$expectedhash  $output
-EOF
-
-        # Check the exit code of the shasum command:
-        CHECKSUM_RESULT=$?
-        set -e
-        if [ $CHECKSUM_RESULT -eq 0 ]; then
-            echo "Parameter file ${filename} has a valid checksum, continuing."
-        else
-            echo "Parameter file ${filename} has a invalid checksum, deleting and re-downloading." >&2
-            rm "$output"
-            fetch_params "$filename" "$output" "$expectedhash"
-        fi
-    fi
-
-    unset -v filename
-    unset -v output
-    unset -v expectedhash
-}
-
-# Use flock to prevent parallel execution.
-lock() {
-    if [ "$uname_S" = "Darwin" ]; then
-        if shlock -f ${LOCKFILE} -p $$; then
-            return 0
-        else
-            return 1
-        fi
-    else
-        # create lock file
-        eval "exec 9>$LOCKFILE"
-        # acquire the lock
-        flock -n 9 \
-            && return 0 \
-            || return 1
-    fi
-}
-
-exit_locked_error() {
-    echo "Only one instance of ${SCRIPT_NAME} can be run at a time." >&2
-    echo "If you are certain no other instance is running, you can try removing" >&2
-    echo "${LOCKFILE}" >&2
-    exit 1
-}
-
-main() {
-
-    lock \
-    || exit_locked_error
-
-    cat <<EOF
-Zcash - ${SCRIPT_NAME}
-
-This script will fetch the Zcash zkSNARK parameters and verify their
-integrity with sha256sum.
-
-If the files are already present and have the correct sha256sum, no
-networking is used. Parameter files with incorrect sha256sums are
-deleted and re-downloaded.
-
-EOF
-
-    # Now create PARAMS_DIR and insert a README if necessary:
-    if ! [ -d "$PARAMS_DIR" ]
-    then
-        mkdir -p "$PARAMS_DIR"
-        README_PATH="$PARAMS_DIR/README"
-        cat >> "$README_PATH" <<EOF
-This directory stores common Zcash zkSNARK parameters. Note that it is
-distinct from the daemon's -datadir argument because the parameters are
-large and may be shared across multiple distinct -datadir's such as when
-setting up test networks.
-EOF
-
-        # This may be the first time the user's run this script, so give
-        # them some info, especially about bandwidth usage:
-        cat <<EOF
-The complete parameters are currently just under 800MB in size, so plan
-accordingly for your bandwidth constraints. If the files are already
-present and have the correct sha256sum, no networking is used.
-
-Creating params directory. For details about this directory, see:
-$README_PATH
-
-EOF
-    fi
-
-    cd "$PARAMS_DIR"
-
-    # Sprout parameters:
-    # Commented out because they are unneeded, but we will eventually update
-    # this to delete the parameters if possible.
-    #fetch_params "$SPROUT_PKEY_NAME" "$PARAMS_DIR/$SPROUT_PKEY_NAME" "8bc20a7f013b2b58970cddd2e7ea028975c88ae7ceb9259a5344a16bc2c0eef7"
-    #fetch_params "$SPROUT_VKEY_NAME" "$PARAMS_DIR/$SPROUT_VKEY_NAME" "4bd498dae0aacfd8e98dc306338d017d9c08dd0918ead18172bd0aec2fc5df82"
-
-    # Sapling parameters:
-    check_and_fetch_params "$SAPLING_SPEND_NAME" "$PARAMS_DIR/$SAPLING_SPEND_NAME" "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13"
-    check_and_fetch_params "$SAPLING_OUTPUT_NAME" "$PARAMS_DIR/$SAPLING_OUTPUT_NAME" "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4"
-    check_and_fetch_params "$SAPLING_SPROUT_GROTH16_NAME" "$PARAMS_DIR/$SAPLING_SPROUT_GROTH16_NAME" "b685d700c60328498fbde589c8c7c484c722b788b265b72af448a5bf0ee55b50"
-}
-
-if [ "${1:-}" = '--testnet' ]
-then
-    echo "NOTE: testnet now uses the mainnet parameters, so the --testnet argument"
-    echo "is no longer needed (ignored)"
-    echo ""
-fi
-
-main
-rm -f $LOCKFILE
 exit 0


Test patch:
diff --git a/src/gtest/utils.cpp b/src/gtest/utils.cpp
index c7d5b6dcd88..97be81e4b10 100644
--- a/src/gtest/utils.cpp
+++ b/src/gtest/utils.cpp
@@ -18,22 +18,14 @@ int GenMax(int n)
 }
 
 void LoadProofParameters() {
-    fs::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
-    fs::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
     fs::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
 
     static_assert(
         sizeof(fs::path::value_type) == sizeof(codeunit),
         "librustzcash not configured correctly");
-    auto sapling_spend_str = sapling_spend.native();
-    auto sapling_output_str = sapling_output.native();
     auto sprout_groth16_str = sprout_groth16.native();
 
     librustzcash_init_zksnark_params(
-        reinterpret_cast<const codeunit*>(sapling_spend_str.c_str()),
-        sapling_spend_str.length(),
-        reinterpret_cast<const codeunit*>(sapling_output_str.c_str()),
-        sapling_output_str.length(),
         reinterpret_cast<const codeunit*>(sprout_groth16_str.c_str()),
         sprout_groth16_str.length(),
         true
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 3b76e0bd3fc..a8ca9bf010b 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -81,22 +81,14 @@ BasicTestingSetup::~BasicTestingSetup()
 
 TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
 {
-    fs::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
-    fs::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
     fs::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
 
     static_assert(
         sizeof(fs::path::value_type) == sizeof(codeunit),
         "librustzcash not configured correctly");
-    auto sapling_spend_str = sapling_spend.native();
-    auto sapling_output_str = sapling_output.native();
     auto sprout_groth16_str = sprout_groth16.native();
 
     librustzcash_init_zksnark_params(
-        reinterpret_cast<const codeunit*>(sapling_spend_str.c_str()),
-        sapling_spend_str.length(),
-        reinterpret_cast<const codeunit*>(sapling_output_str.c_str()),
-        sapling_output_str.length(),
         reinterpret_cast<const codeunit*>(sprout_groth16_str.c_str()),
         sprout_groth16_str.length(),
         // Only load the verifying keys, which some tests need.