From aad883b68ae1fb7a98aa2868bc1bd4a34954bd13 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 25 Oct 2023 09:27:24 +1000 Subject: [PATCH] change(consensus): Build Sprout and Sapling parameters into the zebrad binary, so a download server isn't needed (#7800) * Build sapling parameters into zebrad * Load the sapling parameters from wagyu-zcash-parameters * Reword logs * wget https://github.com/zcash/zcash/raw/master/src/rust/src/sprout-groth16.vk * Load sprout from binary and remove download code * Remove download examples binaries * Remove unused features and dependencies * Remove docs and comments about downloading parameters * Add CHANGELOG entry * Remove parameter cache steps in workflows * Update comment about downloading Co-authored-by: Marek * Fix outdated timeout comments and short timeouts --------- Co-authored-by: Marek --- .github/workflows/ci-coverage.patch.yml | 4 - .github/workflows/ci-coverage.yml | 28 +-- .github/workflows/ci-unit-tests-os.yml | 34 +--- CHANGELOG.md | 25 ++- Cargo.lock | 65 ++++-- Cargo.toml | 8 - README.md | 2 - book/src/dev/continuous-integration.md | 10 +- book/src/user/parameters.md | 76 +------ zebra-consensus/Cargo.toml | 3 +- zebra-consensus/examples/download-params.rs | 11 -- zebra-consensus/examples/get-params-path.rs | 12 -- zebra-consensus/src/config.rs | 12 -- .../src/primitives/groth16/params.rs | 187 +++--------------- .../src/primitives/groth16/sprout-groth16.vk | Bin 0 -> 1828 bytes zebra-test/scripts/shutdown-errors | 6 - zebrad/src/commands/start.rs | 3 - 17 files changed, 121 insertions(+), 365 deletions(-) delete mode 100644 zebra-consensus/examples/download-params.rs delete mode 100644 zebra-consensus/examples/get-params-path.rs create mode 100644 zebra-consensus/src/primitives/groth16/sprout-groth16.vk diff --git a/.github/workflows/ci-coverage.patch.yml b/.github/workflows/ci-coverage.patch.yml index e2defe8ee7b..9b2320d82ee 100644 --- a/.github/workflows/ci-coverage.patch.yml +++ b/.github/workflows/ci-coverage.patch.yml @@ -17,10 +17,6 @@ on: jobs: coverage: name: Coverage on stable - # The large timeout is to accommodate: - # - nightly builds (75 minutes, typically 30-50 minutes) - # - parameter downloads (40 minutes, but only when the cache expires) - timeout-minutes: 115 runs-on: ubuntu-latest steps: diff --git a/.github/workflows/ci-coverage.yml b/.github/workflows/ci-coverage.yml index aea08fbba4f..5d6179fed92 100644 --- a/.github/workflows/ci-coverage.yml +++ b/.github/workflows/ci-coverage.yml @@ -9,6 +9,10 @@ concurrency: on: workflow_dispatch: + + # we build Rust caches on main, + # so they can be shared by all branches: + # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache push: branches: - main @@ -28,6 +32,7 @@ on: # workflow definitions - 'codecov.yml' - '.github/workflows/ci-coverage.yml' + pull_request: paths: - '**/*.rs' @@ -51,9 +56,8 @@ jobs: coverage: name: Coverage on stable # The large timeout is to accommodate: - # - stable builds (typically 30-50 minutes), and - # - parameter downloads (an extra 90 minutes, but only when the cache expires) - timeout-minutes: 140 + # - stable builds (typically 50-90 minutes), and + timeout-minutes: 120 runs-on: ubuntu-latest-xl steps: @@ -84,24 +88,6 @@ jobs: echo "PROPTEST_CASES=1" >> $GITHUB_ENV echo "PROPTEST_MAX_SHRINK_ITERS=0" >> $GITHUB_ENV - # Modified from: - # https://github.com/zcash/librustzcash/blob/c48bb4def2e122289843ddb3cb2984c325c03ca0/.github/workflows/ci.yml#L20-L33 - - name: Fetch path to Zcash parameters - working-directory: ./zebra-consensus - shell: bash - # cargo-llvm-cov doesn't have a silent mode, so we have to extract the path from stderr - run: echo "ZCASH_PARAMS=$(cargo llvm-cov --lcov --no-report run --example get-params-path 2>&1 >/dev/null | tail -1)" >> $GITHUB_ENV - - name: Cache Zcash parameters - id: cache-params - uses: actions/cache@v3 - with: - path: ${{ env.ZCASH_PARAMS }} - key: ${{ runner.os }}-sprout-and-sapling-params - - name: Fetch Zcash parameters - if: steps.cache-params.outputs.cache-hit != 'true' - working-directory: ./zebra-consensus - run: cargo llvm-cov --lcov --no-report run --example download-params - - name: Run Zebra tests run: cargo llvm-cov --lcov --no-report diff --git a/.github/workflows/ci-unit-tests-os.yml b/.github/workflows/ci-unit-tests-os.yml index 3f5d764336e..69ed6ad40bd 100644 --- a/.github/workflows/ci-unit-tests-os.yml +++ b/.github/workflows/ci-unit-tests-os.yml @@ -9,9 +9,6 @@ concurrency: on: workflow_dispatch: - # we build Rust and Zcash parameter caches on main, - # so they can be shared by all branches: - # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache pull_request: paths: @@ -31,6 +28,9 @@ on: # workflow definitions - '.github/workflows/ci-unit-tests-os.yml' + # we build Rust caches on main, + # so they can be shared by all branches: + # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache push: branches: - main @@ -67,9 +67,8 @@ jobs: test: name: Test ${{ matrix.rust }} on ${{ matrix.os }}${{ matrix.features }} # The large timeout is to accommodate: - # - macOS and Windows builds (90 minutes, typically 30-70 minutes), and - # - parameter downloads (an extra 100 minutes, but only when the cache expires) - timeout-minutes: 190 + # - macOS and Windows builds (typically 50-90 minutes), and + timeout-minutes: 120 runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -159,29 +158,6 @@ jobs: echo "PROPTEST_CASES=1" >> $GITHUB_ENV echo "PROPTEST_MAX_SHRINK_ITERS=1024" >> $GITHUB_ENV - # Modified from: - # https://github.com/zcash/librustzcash/blob/c48bb4def2e122289843ddb3cb2984c325c03ca0/.github/workflows/ci.yml#L20-L33 - # - # TODO: - # - split Fetch/Cache Zcash parameters into their own job, - # and use `concurrency:` to limit it to one job per OS - # - split get-params-path and download-params examples into their own crate, - # to speed up compilation - - name: Fetch path to Zcash parameters - working-directory: ./zebra-consensus - shell: bash - run: echo "ZCASH_PARAMS=$(cargo run --release --example get-params-path)" >> $GITHUB_ENV - - name: Cache Zcash parameters - id: cache-params - uses: actions/cache@v3 - with: - path: ${{ env.ZCASH_PARAMS }} - key: ${{ runner.os }}-sprout-and-sapling-params - - name: Fetch Zcash parameters - if: steps.cache-params.outputs.cache-hit != 'true' - working-directory: ./zebra-consensus - run: cargo run --release --example download-params - # Run unit and basic acceptance tests, only showing command output if the test fails. # # If some tests hang, add "-- --nocapture" for just that test, or for all the tests. diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5d9430027..d46c3ec28a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Zebra's mining RPCs are now available in release builds. TODO: rest of intro This release contains the following changes: - + ### Mining RPCs in Production Builds Zebra's mining RPCs are now available in release builds (#7740). Any Zebra instance can be used @@ -21,6 +21,25 @@ read our [mining blog post](https://zfnd.org/experimental-mining-support-in-zebr Please [let us know](https://github.com/ZcashFoundation/zebra/issues/new?assignees=&labels=C-enhancement%2CS-needs-triage&projects=&template=feature_request.yml&title=feature%3A+) if your mining pool needs extra RPC methods or fields. +### Parameters in Binary + +`zebrad` now bundles zk-SNARK parameters directly into its binary. This increases the binary size +by a few megabytes, but these parameters do not need to be downloaded or stored separately. + +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) + +If you have upgraded `zebrad` to 1.4.0 or later, and `zcashd` to 5.7.0 or later, you can delete the +parameter files in these directories to save approximately 700 MB disk space. + +[`zcashd` have deprecated their `fetch-params.sh` script](https://github.com/zcash/zcash/blob/master/doc/release-notes/release-notes-5.7.0.md#deprecation-of-fetch-paramssh), +so it can't be used to retry failed downloads in `zebrad` 1.3.0 and earlier. + +We recommend upgrading to the latest Zebra release to avoid download issues in new installs. + ### Security TODO: rest of changelog @@ -32,9 +51,9 @@ and fixes performance issues and bugs in the mining solution rate RPCs. Progress bars can now be enabled using a config, please help us test them! It contains the following updates: - + ### User Testing: Progress Bars - + Zebra has progress bars! When progress bars are enabled, you can see Zebra's blocks, transactions, and peer connections in your terminal. We're asking Zebra users to test this feature, and give us [feedback on the forums](https://forum.zcashcommunity.com/t/zebra-progress-bars/44485). diff --git a/Cargo.lock b/Cargo.lock index 30bd8d1a5e6..4e3c6484003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2486,19 +2486,6 @@ dependencies = [ "adler", ] -[[package]] -name = "minreq" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3371dfc7b772c540da1380123674a8e20583aca99907087d990ca58cf44203" -dependencies = [ - "log", - "once_cell", - "rustls", - "rustls-webpki", - "webpki-roots", -] - [[package]] name = "mio" version = "0.8.8" @@ -4916,6 +4903,56 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[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" @@ -5373,7 +5410,6 @@ dependencies = [ "jubjub", "known-folders", "lazy_static", - "minreq", "rand_core 0.6.4", "redjubjub", "tracing", @@ -5516,6 +5552,7 @@ dependencies = [ "tracing-error", "tracing-futures", "tracing-subscriber", + "wagyu-zcash-parameters", "zcash_proofs", "zebra-chain", "zebra-node-services", diff --git a/Cargo.toml b/Cargo.toml index 0f81f34fa45..2146e9b487f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,17 +47,9 @@ opt-level = 3 [profile.dev.package.bls12_381] opt-level = 3 -# Cryptographic and parameter download crates - [profile.dev.package.zcash_proofs] opt-level = 3 -[profile.dev.package.minreq] -opt-level = 3 - -[profile.dev.package.rustls] -opt-level = 3 - [profile.dev.package.ring] opt-level = 3 diff --git a/README.md b/README.md index 3d61da9b325..4cbb72e4c63 100644 --- a/README.md +++ b/README.md @@ -163,8 +163,6 @@ There are a few bugs in Zebra that we're still working on fixing: - Zebra currently gossips and connects to [private IP addresses](https://en.wikipedia.org/wiki/IP_address#Private_addresses), we want to [disable private IPs but provide a config (#3117)](https://github.com/ZcashFoundation/zebra/issues/3117) in an upcoming release -- If Zebra fails downloading the Zcash parameters, use [the Zcash parameters download script](https://github.com/zcash/zcash/blob/master/zcutil/fetch-params.sh) instead. - - Block download and verification sometimes times out during Zebra's initial sync [#5709](https://github.com/ZcashFoundation/zebra/issues/5709). The full sync still finishes reasonably quickly. - Rust 1.70 [causes crashes during shutdown on macOS x86_64 (#6812)](https://github.com/ZcashFoundation/zebra/issues/6812). The state cache should stay valid despite the crash. diff --git a/book/src/dev/continuous-integration.md b/book/src/dev/continuous-integration.md index a460fc91cc1..4310f904013 100644 --- a/book/src/dev/continuous-integration.md +++ b/book/src/dev/continuous-integration.md @@ -178,14 +178,13 @@ To fix duplicate dependencies, follow these steps until the duplicate dependenci 2. If there are any "skip tree root was not found in the dependency graph" warnings, delete those versions from `deny.toml` -### Fixing Disk Full Errors and Zcash Parameter Errors +### Fixing Disk Full Errors If the Docker cached state disks are full, increase the disk sizes in: - [deploy-gcp-tests.yml](https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/deploy-gcp-tests.yml) - [continous-delivery.yml](https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/continous-delivery.yml) -If the GitHub Actions disks are full, or the Zcash parameter downloads time out without any network messages or errors, -follow these steps until the errors are fixed: +If the GitHub Actions disks are full, follow these steps until the errors are fixed: 0. Check if error is also happening on the `main` branch. If it is, skip the next step. 1. Update your branch to the latest `main` branch, this builds with all the latest dependencies in the `main` branch cache. @@ -194,11 +193,6 @@ follow these steps until the errors are fixed: These errors often happen after a new compiler version is released, because the caches can end up with files from both compiler versions. -If the Zcash Parameter downloads have an error loading the parameters: -1. Clear the Zcash parameter caches for all branches, including `main` - -The correct `*-sprout-and-sapling-params` caches should be around 765 MB. - You can find a list of caches using: ```sh gh api -H "Accept: application/vnd.github+json" repos/ZcashFoundation/Zebra/actions/caches diff --git a/book/src/user/parameters.md b/book/src/user/parameters.md index 7bfff2c9861..ee1aced0dd1 100644 --- a/book/src/user/parameters.md +++ b/book/src/user/parameters.md @@ -8,83 +8,15 @@ https://zips.z.cash/protocol/protocol.pdf#groth The Groth16 proving system requires a trusted setup, this is a set of predefined parameters that every node should possess to verify the proofs that will show up in the blockchain. -These parameters are in the form of files, they are basically predefined keys that will allow verification of the circuits. They were initially obtained by [this process](https://eprint.iacr.org/2017/1050.pdf). +These parameters are built into the `zebrad` binary. They are predefined keys that will allow verification of the circuits. They were initially obtained by [this process](https://eprint.iacr.org/2017/1050.pdf). -3 files are needed, one for each circuit, this is part of the Zcash consensus protocol: +3 parameters are needed, one for each circuit, this is part of the Zcash consensus protocol: https://zips.z.cash/protocol/protocol.pdf#grothparameters -In Zebra, these 3 public files are mapped into 2 structures: - -```rust -/// Groth16 Zero-Knowledge Proof spend and output parameters for the Sapling circuit. -pub struct SaplingParameters { - pub spend: groth16::Parameters, - pub spend_prepared_verifying_key: groth16::PreparedVerifyingKey, - pub output: groth16::Parameters, - pub output_prepared_verifying_key: groth16::PreparedVerifyingKey, -} -/// Groth16 Zero-Knowledge Proof spend parameters for the Sprout circuit. -/// -/// New Sprout outputs were disabled by the Canopy network upgrade. -pub struct SproutParameters { - pub joinsplit_prepared_verifying_key: groth16::PreparedVerifyingKey, -} -``` - Zebra uses the [bellman crate groth16 implementation](https://github.com/zkcrypto/bellman/blob/main/src/groth16/mod.rs) for all groth16 types. Each time a transaction has any sprout joinsplit, sapling spend or sapling output these loaded parameters will be used for the verification process. Zebra verifies in parallel and by batches, these parameters are used on each verification done. -There are 2 different zebrad commands to get these parameters from the internet and load them into zebra: - -## zebrad download - -When this command is executed Zebra will create a path for each parameter file. For example, in linux, parameter files will be at: - -- `/home/$USER/.zcash-params/sapling-output.params` -- `/home/$USER/.zcash-params/sapling-spend.params` -- `/home/$USER/.zcash-params/sprout-groth16.params` - -These are the same parameter paths used by `zcashd` and [fetch-params.sh](https://github.com/zcash/zcash/blob/master/zcutil/fetch-params.sh). - -These files are available for [download](https://download.z.cash/downloads/) and their hash for verification is part of the Zcash protocol: - -https://zips.z.cash/protocol/protocol.pdf#grothparameters - -Zebra will next use the [zcash_proofs](https://github.com/zcash/librustzcash/tree/main/zcash_proofs) crate to call a function with the 3 paths as arguments. - -Function `zcash_proofs::load_parameters()` will take the 3 paths, check if the data is already there, verify the hashes and download the content if needed. - -```sh -$ ./target/release/zebrad download -2022-12-29T16:54:50.273253Z INFO zebrad::components::tracing::component: started tracing component filter="info" TRACING_STATIC_MAX_LEVEL=LevelFilter::TRACE LOG_STATIC_MAX_LEVEL=Trace -2022-12-29T16:54:50.274611Z INFO {zebrad="535d0ad" net="Main"}: zebrad::application: initialized rayon thread pool for CPU-bound tasks num_threads=12 -2022-12-29T16:54:50.275486Z INFO {zebrad="535d0ad" net="Main"}: zebrad::commands::download: checking if Zcash Sapling and Sprout parameters have been downloaded -2022-12-29T16:54:50.312716Z INFO {zebrad="535d0ad" net="Main"}: zebra_consensus::primitives::groth16::params: checking and loading Zcash Sapling and Sprout parameters -2022-12-29T16:54:56.865148Z INFO {zebrad="535d0ad" net="Main"}: zebra_consensus::primitives::groth16::params: Zcash Sapling and Sprout parameters downloaded and/or verified -$ -``` - -## zebrad start - -The alternative way is to let zebra do the above process at startup. - -Before Zebra attempts to verify any of the 3 mentioned circuits it needs to have the parameters in place. For this reason zebra start will check for the parameters and download them if needed each time it is started. - -At zebra startup, when initializing the verifiers, a separate task is created to do the same as the `zebra download` command. This allows Zebra sync to make progress before having the parameters. Note that these parameters are needed after Sapling activation which happens at block `419_200` in the Mainnet and block `15` in the Testnet. Zebra will wait for the parameters to download before verifying those blocks and above. - -If the parameters were already downloaded and they are already in place the same function `zcash_proofs::load_parameters()` will verify them against the consensus hashes. If they are not there or the hash is not the same then `zcash_proofs::load_parameters()` will download. - -```sh -$ ./target/release/zebrad start -... -2022-12-29T17:04:21.948096Z INFO {zebrad="535d0ad" net="Main"}: zebrad::commands::start: initializing verifiers -... -zebra_consensus::primitives::groth16::params: checking and loading Zcash Sapling and Sprout parameters -... -zebra_consensus::primitives::groth16::params: Zcash Sapling and Sprout parameters downloaded and/or verified -... -debug_skip_parameter_preload=false}: zebra_consensus::chain: Groth16 pre-download and check task finished -... -``` +The first time any parameters are used, Zebra automatically parses all of the parameters. This work +is only done once. diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index f674e18777c..21ab5346343 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -60,7 +60,8 @@ tracing-futures = "0.2.5" orchard = "0.6.0" -zcash_proofs = { version = "0.13.0-rc.1", features = ["local-prover", "multicore", "download-params"] } +zcash_proofs = { version = "0.13.0-rc.1", features = ["multicore" ] } +wagyu-zcash-parameters = "0.2.0" tower-fallback = { path = "../tower-fallback/", version = "0.2.41-beta.6" } tower-batch-control = { path = "../tower-batch-control/", version = "0.2.41-beta.6" } diff --git a/zebra-consensus/examples/download-params.rs b/zebra-consensus/examples/download-params.rs deleted file mode 100644 index 36444269907..00000000000 --- a/zebra-consensus/examples/download-params.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Download the Sapling and Sprout Groth16 parameters if needed, -//! check they were downloaded correctly, and load them into Zebra. - -// Has the same functionality as: -// https://github.com/zcash/librustzcash/blob/c48bb4def2e122289843ddb3cb2984c325c03ca0/zcash_proofs/examples/download-params.rs - -fn main() { - // The lazy static initializer does the download, if needed, - // and the file hash checks. - lazy_static::initialize(&zebra_consensus::groth16::GROTH16_PARAMETERS); -} diff --git a/zebra-consensus/examples/get-params-path.rs b/zebra-consensus/examples/get-params-path.rs deleted file mode 100644 index 1a6e98d7251..00000000000 --- a/zebra-consensus/examples/get-params-path.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Print the Zcash parameter directory path to standard output. - -// Modified from: -// https://github.com/zcash/librustzcash/blob/c48bb4def2e122289843ddb3cb2984c325c03ca0/zcash_proofs/examples/get-params-path.rs - -#[allow(clippy::print_stdout)] -fn main() { - let path = zebra_consensus::groth16::Groth16Parameters::directory(); - if let Some(path) = path.to_str() { - println!("{path}"); - } -} diff --git a/zebra-consensus/src/config.rs b/zebra-consensus/src/config.rs index ea1e771ecde..8bad913b8c6 100644 --- a/zebra-consensus/src/config.rs +++ b/zebra-consensus/src/config.rs @@ -4,18 +4,6 @@ use serde::{Deserialize, Serialize}; /// Configuration for parallel semantic verification: /// -/// -/// Automatically downloads the Zcash Sprout and Sapling parameters to the default directory: -/// - Linux: `$HOME/.zcash-params` -/// - macOS: `$HOME/Library/Application Support/ZcashParams` -/// - Windows: `%APPDATA%\ZcashParams` or `C:\Users\%USERNAME%\AppData\ZcashParams` -/// -/// # Security -/// -/// If you are running Zebra with elevated permissions ("root"), create the -/// parameters directory before running Zebra, and make sure the Zebra user -/// account has exclusive access to that directory, and other users can't modify -/// its parent directories. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(deny_unknown_fields, default)] pub struct Config { diff --git a/zebra-consensus/src/primitives/groth16/params.rs b/zebra-consensus/src/primitives/groth16/params.rs index 52fb20b7595..3129491d490 100644 --- a/zebra-consensus/src/primitives/groth16/params.rs +++ b/zebra-consensus/src/primitives/groth16/params.rs @@ -1,37 +1,16 @@ -//! Downloading, checking, and loading Groth16 Sapling and Sprout parameters. - -use std::path::{Path, PathBuf}; +//! Loading and checking correctness of Groth16 Sapling and Sprout parameters. use bellman::groth16; use bls12_381::Bls12; -use zcash_proofs::SaplingParameterPaths; - -use crate::BoxError; - -/// The timeout for each parameter file download, in seconds. -/// -/// Zebra assumes that it's running on at least a 10 Mbps connection. -/// So the parameter files should download in about 15 minutes using `zebrad download`. -/// But `zebrad start` downloads blocks at the same time, so we allow some extra time. -pub const PARAMETER_DOWNLOAD_TIMEOUT: u64 = 60 * 60; - -/// The maximum number of times Zebra retries to download the parameters. -/// -/// Zebra will retry the download only if the previous attempt fails. -pub const PARAMETER_DOWNLOAD_MAX_RETRIES: usize = 2; lazy_static::lazy_static! { /// Groth16 Zero-Knowledge Proof parameters for the Sapling and Sprout circuits. /// - /// This static is accessed when Zebra: - /// - /// - needs to download and cache the parameters to a shared directory, or - /// - checks the file hashes for both newly downloaded and previously cached files, or - /// - loads the parameters. + /// This static is accessed when Zebra needs to use these parameters for verification. /// /// # Panics /// - /// If the downloaded or pre-existing parameter files are invalid. + /// If the parameter data in the `zebrad` binary is invalid. pub static ref GROTH16_PARAMETERS: Groth16Parameters = Groth16Parameters::new(); } @@ -55,164 +34,54 @@ pub struct SaplingParameters { /// Groth16 Zero-Knowledge Proof spend parameters for the Sprout circuit. /// -/// New Sprout outputs were disabled by the Canopy network upgrade. +/// Adding value to the Sprout pool was disabled by the Canopy network upgrade. pub struct SproutParameters { pub joinsplit_prepared_verifying_key: groth16::PreparedVerifyingKey, } impl Groth16Parameters { - /// Loads the Sprout and Sapling Groth16 parameters, checking the sizes and hashes of the files. - /// - /// If the parameters are not present, they are automatically downloaded and cached. + /// Loads the Sprout and Sapling Groth16 parameters from the `zebrad` binary, and checks that + /// the data is valid. /// /// # Panics /// - /// - If the parameters were downloaded to a wrong path. - /// - After [`PARAMETER_DOWNLOAD_MAX_RETRIES`] failed download retries. - /// - If the downloaded or pre-existing parameter files are invalid. + /// If the parameter data in the `zebrad` binary is invalid. fn new() -> Groth16Parameters { - let params_directory = Groth16Parameters::directory(); - let sapling_spend_path = params_directory.join(zcash_proofs::SAPLING_SPEND_NAME); - let sapling_output_path = params_directory.join(zcash_proofs::SAPLING_OUTPUT_NAME); - let sprout_path = params_directory.join(zcash_proofs::SPROUT_NAME); + tracing::info!("checking and loading Zcash Sapling and Sprout parameters"); - Groth16Parameters::download_sapling_parameters(&sapling_spend_path, &sapling_output_path); - Groth16Parameters::download_sprout_parameters(&sprout_path); + let (sapling_spend_bytes, sapling_output_bytes) = + wagyu_zcash_parameters::load_sapling_parameters(); + let sprout_vk_bytes = include_bytes!("sprout-groth16.vk"); - // TODO: if loading fails, log a message including `failure_hint` - tracing::info!("checking and loading Zcash Sapling and Sprout parameters"); - let parameters = zcash_proofs::load_parameters( - &sapling_spend_path, - &sapling_output_path, - Some(&sprout_path), + let sapling_parameters = zcash_proofs::parse_parameters( + sapling_spend_bytes.as_slice(), + sapling_output_bytes.as_slice(), + // This API expects the full sprout parameter file, not just the verifying key. + None, ); let sapling = SaplingParameters { - spend: parameters.spend_params, - spend_prepared_verifying_key: parameters.spend_vk, - output: parameters.output_params, - output_prepared_verifying_key: parameters.output_vk, + spend: sapling_parameters.spend_params, + spend_prepared_verifying_key: sapling_parameters.spend_vk, + output: sapling_parameters.output_params, + output_prepared_verifying_key: sapling_parameters.output_vk, }; + let sprout_vk = groth16::VerifyingKey::::read(&sprout_vk_bytes[..]) + .expect("should be able to parse Sprout verification key"); + let sprout_vk = groth16::prepare_verifying_key(&sprout_vk); + let sprout = SproutParameters { - joinsplit_prepared_verifying_key: parameters - .sprout_vk - .expect("unreachable code: sprout loader panics on failure"), + joinsplit_prepared_verifying_key: sprout_vk, }; - tracing::info!("Zcash Sapling and Sprout parameters downloaded and/or verified"); + tracing::info!("Zcash Sapling and Sprout parameters loaded and verified"); Groth16Parameters { sapling, sprout } } - /// Returns the path to the Groth16 parameters directory. - pub fn directory() -> PathBuf { - zcash_proofs::default_params_folder().expect("unable to find user home directory") - } - - /// Returns a hint that helps users recover from parameter download failures. + /// Returns a hint that helps users recover from parameter loading failures. pub fn failure_hint() -> String { - format!( - "Hint: try deleting {:?}, then running 'zebrad download' to re-download the parameters", - Groth16Parameters::directory(), - ) - } - - /// Downloads the Sapling parameters. - /// - /// # Panics - /// - /// - If the parameters were downloaded to a wrong path. - /// - After [`PARAMETER_DOWNLOAD_MAX_RETRIES`] failed download retries. - fn download_sapling_parameters(sapling_spend_path: &Path, sapling_output_path: &Path) { - // TODO: instead of the path check, add a zcash_proofs argument to skip hashing existing files - // (we check them on load anyway) - if !sapling_spend_path.exists() || !sapling_output_path.exists() { - tracing::info!("downloading Zcash Sapling parameters"); - - let mut retries = 0; - while let Err(error) = Groth16Parameters::download_sapling_parameters_once( - sapling_spend_path, - sapling_output_path, - ) { - retries += 1; - if retries > PARAMETER_DOWNLOAD_MAX_RETRIES { - panic!( - "error downloading Sapling parameter files after {} retries. {:?} {}", - PARAMETER_DOWNLOAD_MAX_RETRIES, - error, - Groth16Parameters::failure_hint(), - ); - } else { - tracing::info!( - ?error, - "error downloading Zcash Sapling parameters, retrying" - ); - } - } - } - } - - /// Tries to download the Sapling parameters once and returns the result. - /// - /// # Panics - /// - /// If the parameters were downloaded to paths different to `sapling_spend_path` or - /// `sapling_output_path`. - fn download_sapling_parameters_once( - sapling_spend_path: &Path, - sapling_output_path: &Path, - ) -> Result { - let new_sapling_paths = - zcash_proofs::download_sapling_parameters(Some(PARAMETER_DOWNLOAD_TIMEOUT))?; - - assert_eq!(sapling_spend_path, new_sapling_paths.spend); - assert_eq!(sapling_output_path, new_sapling_paths.output); - - Ok(new_sapling_paths) - } - - /// Downloads the Sprout parameters. - /// - /// # Panics - /// - /// - If the parameters were downloaded to a wrong path. - /// - After [`PARAMETER_DOWNLOAD_MAX_RETRIES`] failed download retries. - fn download_sprout_parameters(sprout_path: &Path) { - if !sprout_path.exists() { - tracing::info!("downloading Zcash Sprout parameters"); - - let mut retries = 0; - while let Err(error) = Groth16Parameters::download_sprout_parameters_once(sprout_path) { - retries += 1; - if retries > PARAMETER_DOWNLOAD_MAX_RETRIES { - panic!( - "error downloading Sprout parameter files after {} retries. {:?} {}", - PARAMETER_DOWNLOAD_MAX_RETRIES, - error, - Groth16Parameters::failure_hint(), - ); - } else { - tracing::info!( - ?error, - "error downloading Zcash Sprout parameters, retrying" - ); - } - } - } - } - - /// Tries to download the Sprout parameters once and returns the result. - /// - /// # Panics - /// - /// If the parameters were downloaded to a path different to `sprout_path`. - fn download_sprout_parameters_once(sprout_path: &Path) -> Result { - let new_sprout_path = - zcash_proofs::download_sprout_parameters(Some(PARAMETER_DOWNLOAD_TIMEOUT))?; - - assert_eq!(sprout_path, new_sprout_path); - - Ok(new_sprout_path) + "Hint: re-run `zebrad` or re-install it from a trusted source".to_string() } } diff --git a/zebra-consensus/src/primitives/groth16/sprout-groth16.vk b/zebra-consensus/src/primitives/groth16/sprout-groth16.vk new file mode 100644 index 0000000000000000000000000000000000000000..60f6ee96e0560e3d1e8a025a0e9a51334c9956af GIT binary patch literal 1828 zcmV+<2iy1!xPs4Jv*=cT7PQ+Ja@5iFqyCLz@ZT=DrO%}Z25>6<==>!!UbXCnoG2Kw zVGAx9t3+L_atpEYu+1|z_o1xDEAg|VA%bFL+h$cL_=lKk9Z??60A7mpFx~5@Pb7ZA)drs zCc*mEFi}p}k)Y57I?mrTi6Rg#m9ys1ehT`O#fqd9fMXxQ$~NU%u2KC8L2H4BMGGkK zCBz}){}j`Yn!TFx@dRs;OH->i>8`t`gUcl-PFy1TG!ZG7Qc$4-RDI>p1>Z;}UwpDy z79vyCZ@g$N5NaOF2WD=+btI!?2>aCgyu zq%TkT*e=9Ys`NP&qtJP15gIx)j}?Aoz$c0m;45HKai3s)tka-~Cr@QrYtYb{AhsH{ z+F`rge^5y?Oz{#ElwDWltbGMt1S@_5N}{sxj|!0{2n8oC#Sl@(qmtkSS6!i$;9J}7>Lr(>@sbdsxAE}5%8 zHw`CT>>Z)1sRv*1UwOU^<<%#0eQptq$<4;vE;Smh{hO+cz0;>{LYiq&V9_j+I?2pC ztfGnGlT?NXxF`V@Iu|O;3oLecMbEuxvDh=fGn&Rc`Qz;o7}^4~o=j5p8Tw`uEs$D+ zEwmlh0cj!?*rXk5SI}M91)wgsSEDwI)zSYFif^$h1a`a`dk%|i&$xQVRPAHajA)YX zsG|)F6l1x%#9}#|Z)n1Z^RN-@;`TQ?ljHi^RNRy;PGy<^z8jX!0vK5`hHD(n$TmFm6#000UNm-)OSL@z4X z5Ga(*OKMa(!By}_4_<|e zX%ID&?F{NkB)OO3g6xA_zMTS1@5_6f3VI!9nn!?6)AC9l-Y!Z^2+6ZHlXLEa>$XeS@o7# zyTD5dmbZa`_Zbl-_26WpD!=$}CsAXjZ{8!6@r$)cskujfd?kI4J9}vr zJq&HxqMb8dodkq56Uh$*kdJC~Sf@QWIhH7L;*`ndd>)KM3pSw;x8tangUYEFu6hgj zjB$}xk)orU)F^68bQ7W410sy-)gypGF!DOBSl5$OLE!U$OfT@=<*ypGy`Yc7n` zXiSRurR8tm&c%b7O zJSavKKFzl#z1()()9l&$6b?d|SOK{h)CJo*Y=6^P!-g`c7g&1OHq4(L!7xCzUI$UH z=HbFNn={F3#vdQC;#=|p8)FC=fP$Fv*eMX)