diff --git a/.github/workflows/ci-unit-tests-os.patch.yml b/.github/workflows/ci-unit-tests-os.patch.yml index 549f1809a51..4a97eb719f5 100644 --- a/.github/workflows/ci-unit-tests-os.patch.yml +++ b/.github/workflows/ci-unit-tests-os.patch.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest] rust: [stable, beta] features: [""] exclude: diff --git a/.github/workflows/ci-unit-tests-os.yml b/.github/workflows/ci-unit-tests-os.yml index bbfa6dc1d6e..c433bf82163 100644 --- a/.github/workflows/ci-unit-tests-os.yml +++ b/.github/workflows/ci-unit-tests-os.yml @@ -74,8 +74,7 @@ jobs: fail-fast: false matrix: # TODO: Windows was removed for now, see https://github.com/ZcashFoundation/zebra/issues/3801 - # TODO: macOS tests were removed for now, see https://github.com/ZcashFoundation/zebra/issues/6824 - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest] rust: [stable, beta] # TODO: When vars.EXPERIMENTAL_FEATURES has features in it, add it here. # Or work out a way to trim the space from the variable: GitHub doesn't allow empty variables. diff --git a/.github/workflows/sub-build-zcash-params.yml b/.github/workflows/sub-build-zcash-params.yml deleted file mode 100644 index ee08b6fd3c2..00000000000 --- a/.github/workflows/sub-build-zcash-params.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build zcash-params - -# Ensures that only one workflow task will run at a time. Previous deployments, if -# already in process, won't get cancelled. Instead, we let the first to complete -# then queue the latest pending workflow, cancelling any workflows in between -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -on: - workflow_dispatch: - inputs: - no_cache: - description: 'Disable the Docker cache for this build' - required: false - type: boolean - default: false - - push: - branches: - - 'main' - paths: - # parameter download code - - 'zebra-consensus/src/primitives/groth16/params.rs' - - 'zebra-consensus/src/router.rs' - - 'zebrad/src/commands/download.rs' - - 'zebrad/src/commands/start.rs' - # workflow definitions - - 'docker/zcash-params/Dockerfile' - - '.dockerignore' - - '.github/workflows/sub-build-zcash-params.yml' - - '.github/workflows/sub-build-docker-image.yml' - -jobs: - build: - name: Build Zcash Params Docker - uses: ./.github/workflows/sub-build-docker-image.yml - with: - dockerfile_path: ./docker/zcash-params/Dockerfile - dockerfile_target: release - image_name: zcash-params - no_cache: ${{ inputs.no_cache || false }} - rust_backtrace: full - rust_lib_backtrace: full - rust_log: info diff --git a/CHANGELOG.md b/CHANGELOG.md index d46c3ec28a6..beda30e185b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org). ## [Zebra 1.4.0](https://github.com/ZcashFoundation/zebra/releases/tag/v1.4.0) - TODO: DATE -Zebra's mining RPCs are now available in release builds. TODO: rest of intro +Zebra's mining RPCs are now available in release builds. Our Docker images are significantly smaller, +because the smaller Zcash verification parameters are now built into the `zebrad` binary. +TODO: rest of intro This release contains the following changes: @@ -21,10 +23,12 @@ 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 +### Zcash Parameters in `zebrad` 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. +by a few megabytes, but reduces the size of the Docker image by around 600 MB because +the parameters don't contain the Sprout proving key anymore. The `zebrad download` +command does nothing, so it has been removed. Previously, parameters were stored by default in these locations: diff --git a/book/src/dev/state-db-upgrades.md b/book/src/dev/state-db-upgrades.md index db5e4bce868..1c162c8ae29 100644 --- a/book/src/dev/state-db-upgrades.md +++ b/book/src/dev/state-db-upgrades.md @@ -1,18 +1,64 @@ # Zebra Cached State Database Implementation +## Current Implementation + +### Verification Modes +[verification]: #verification + +Zebra's state has two verification modes: +- block hash checkpoints, and +- full verification. + +This means that verification uses two different codepaths, and they must produce the same results. + +By default, Zebra uses as many checkpoints as it can, because they are more secure against rollbacks +(and some other kinds of chain attacks). Then it uses full verification for the last few thousand +blocks. + +When Zebra gets more checkpoints in each new release, it checks the previously verified cached +state against those checkpoints. This checks that the two codepaths produce the same results. + ## Upgrading the State Database +[upgrades]: #upgrades For most state upgrades, we want to modify the database format of the existing database. If we change the major database version, every user needs to re-download and re-verify all the blocks, which can take days. +### Writing Blocks to the State +[write-block]: #write-block + +Blocks can be written to the database via two different code paths, and both must produce the same results: + +- Upgrading a pre-existing database to the latest format +- Writing newly-synced blocks in the latest format + +This code is high risk, because discovering bugs is tricky, and fixing bugs can require a full reset +and re-write of an entire column family. + +Most Zebra instances will do an upgrade, because they already have a cached state, and upgrades are +faster. But we run a full sync in CI every week, because new users use that codepath. (And it is +their first experience of Zebra.) + +When Zebra starts up and shuts down (and periodically in CI tests), we run checks on the state +format. This makes sure that the two codepaths produce the same state on disk. + +To reduce code and testing complexity: +- when a previous Zebra version opens a newer state, the entire state is considered to have that lower version, and +- when a newer Zebra version opens an older state, each required upgrade is run on the entire state. + ### In-Place Upgrade Goals +[upgrade-goals]: #upgrade-goals +Here are the goals of in-place upgrades: - avoid a full download and rebuild of the state -- the previous state format must be able to be loaded by the new state +- Zebra must be able to upgrade the format from previous minor or patch versions of its disk format + (Major disk format versions are breaking changes. They create a new empty state and re-sync the whole chain.) - this is checked the first time CI runs on a PR with a new state version. After the first CI run, the cached state is marked as upgraded, so the upgrade doesn't run again. If CI fails on the first run, any cached states with that version should be deleted. +- the upgrade and full sync formats must be identical + - this is partially checked by the state validity checks for each upgrade (see above) - previous zebra versions should be able to load the new format - this is checked by other PRs running using the upgraded cached state, but only if a Rust PR runs after the new PR's CI finishes, but before it merges @@ -30,17 +76,26 @@ This means that: - it can't give incorrect results, because that can affect verification or wallets - it can return an error - it can only return an `Option` if the caller handles it correctly -- multiple upgrades must produce a valid state format +- full syncs and upgrades must write the same format + - the same write method should be called from both the full sync and upgrade code, + this helps prevent data inconsistencies +- repeated upgrades must produce a valid state format - if Zebra is restarted, the format upgrade will run multiple times - if an older Zebra version opens the state, data can be written in an older format -- the format must be valid before and after each database transaction or API call, because an upgrade can be cancelled at any time +- the format must be valid before and after each database transaction or API call, because an + upgrade can be cancelled at any time - multi-column family changes should made in database transactions - - if you are building new column family, disable state queries, then enable them once it's done + - if you are building new column family: + - disable state queries, then enable them once it's done, or + - do the upgrade in an order that produces correct results + (for example, some data is valid from genesis forward, and some from the tip backward) - if each database API call produces a valid format, transactions aren't needed -If there is an upgrade failure, it can panic and tell the user to delete their cached state and re-launch Zebra. +If there is an upgrade failure, panic and tell the user to delete their cached state and re-launch +Zebra. -### Performance Constraints +#### Performance Constraints +[performance]: #performance Some column family access patterns can lead to very poor performance. @@ -62,17 +117,50 @@ But we need to use iterators for some operations, so our alternatives are (in pr Currently only UTXOs require key deletion, and only `utxo_loc_by_transparent_addr_loc` requires deletion and iterators. -### Implementation Steps +### Required Tests +[testing]: #testing + +State upgrades are a high-risk change. They permanently modify the state format on production Zebra +instances. Format issues are tricky to diagnose, and require extensive testing and a new release to +fix. Deleting and rebuilding an entire column family can also be costly, taking minutes or hours the +first time a cached state is upgraded to a new Zebra release. -- [ ] update the [database format](https://github.com/ZcashFoundation/zebra/blob/main/book/src/dev/state-db-upgrades.md#current) in the Zebra docs -- [ ] increment the state minor version -- [ ] write the new format in the block write task -- [ ] update older formats in the format upgrade task -- [ ] test that the new format works when creating a new state, and updating an older state +Some format bugs can't be fixed, and require an entire rebuild of the state. For example, deleting +or corrupting transactions or block headers. -See the [upgrade design docs](https://github.com/ZcashFoundation/zebra/blob/main/book/src/dev/state-db-upgrades.md#design) for more details. +So testing format upgrades is extremely important. Every state format upgrade should test: +- new format serializations +- new calculations or data processing +- the upgrade produces a valid format +- a full sync produces a valid format -These steps can be copied into tickets. +Together, the tests should cover every code path. For example, the subtrees needed mid-block, +end-of-block, sapling, and orchard tests. They mainly used the validity checks for coverage. + +Each test should be followed by a restart, a sync of 200+ blocks, and another restart. This +simulates typical user behaviour. + +And ideally: +- An upgrade from the earliest supported Zebra version + (the CI sync-past-checkpoint tests do this on every PR) + +#### Manually Triggering a Format Upgrade +[manual-upgrade]: #manual-upgrade + +Zebra stores the current state minor and patch versions in a `version` file in the database +directory. This path varies based on the OS, major state version, network, and config. + +For example, the default mainnet state version on Linux is at: +`~/.cache/zebra/state/v25/mainnet/version` + +To upgrade a cached Zebra state from `v25.0.0` to the latest disk format, delete the version file. +To upgrade from a specific version `v25.x.y`, edit the file so it contains `x.y`. + +Editing the file and running Zebra will trigger a re-upgrade over an existing state. +Re-upgrades can hide format bugs. For example, if the old code was correct, and the +new code skips blocks, the validity checks won't find that bug. + +So it is better to test with a full sync, and an older cached state. ## Current State Database Format [current]: #current @@ -124,8 +212,13 @@ We use the following rocksdb column families: | `history_tree` | `()` | `NonEmptyHistoryTree` | Update | | `tip_chain_value_pool` | `()` | `ValueBalance` | Update | -Zcash structures are encoded using `ZcashSerialize`/`ZcashDeserialize`. -Other structures are encoded using `IntoDisk`/`FromDisk`. +### Data Formats +[rocksdb-data-format]: #rocksdb-data-format + +We use big-endian encoding for keys, to allow database index prefix searches. + +Most Zcash protocol structures are encoded using `ZcashSerialize`/`ZcashDeserialize`. +Other structures are encoded using custom `IntoDisk`/`FromDisk` implementations. Block and Transaction Data: - `Height`: 24 bits, big-endian, unsigned (allows for ~30 years worth of blocks) @@ -145,17 +238,21 @@ Block and Transaction Data: - `NoteCommitmentSubtreeIndex`: 16 bits, big-endian, unsigned - `NoteCommitmentSubtreeData<{sapling, orchard}::tree::Node>`: `Height \|\| {sapling, orchard}::tree::Node` -We use big-endian encoding for keys, to allow database index prefix searches. - Amounts: - `Amount`: 64 bits, little-endian, signed - `ValueBalance`: `[Amount; 4]` -Derived Formats: +Derived Formats (legacy): - `*::NoteCommitmentTree`: `bincode` using `serde` - stored note commitment trees always have cached roots -- `NonEmptyHistoryTree`: `bincode` using `serde`, using `zcash_history`'s `serde` implementation +- `NonEmptyHistoryTree`: `bincode` using `serde`, using our copy of an old `zcash_history` `serde` + implementation + +`bincode` is a risky format to use, because it depends on the exact order and type of struct fields. +Do not use it for new column families. +#### Address Format +[rocksdb-address-format]: #rocksdb-address-format The following figure helps visualizing the address index, which is the most complicated part. Numbers in brackets are array sizes; bold arrows are compositions (i.e. `TransactionLocation` is the @@ -200,6 +297,7 @@ Each column family handles updates differently, based on its specific consensus - Each key-value entry is created once. - Keys can be deleted, but values are never updated. - Code called by ReadStateService must ignore deleted keys, or use a read lock. + - We avoid deleting keys, and avoid using iterators on `Delete` column families, for performance. - TODO: should we prevent re-inserts of keys that have been deleted? - Update: - Each key-value entry is created once. @@ -353,8 +451,6 @@ So they should not be used for consensus-critical checks. the Merkle tree nodes as required to insert new items. For each block committed, the old tree is deleted and a new one is inserted by its new height. - **TODO:** store the sprout note commitment tree by `()`, - to avoid ReadStateService concurrent write issues. - The `{sapling, orchard}_note_commitment_tree` stores the note commitment tree state for every height, for the specific pool. Each tree is stored @@ -368,7 +464,6 @@ So they should not be used for consensus-critical checks. state. There is always a single entry for it. The tree is stored as the set of "peaks" of the "Merkle mountain range" tree structure, which is what is required to insert new items. - **TODO:** store the history tree by `()`, to avoid ReadStateService concurrent write issues. - Each `*_anchors` stores the anchor (the root of a Merkle tree) of the note commitment tree of a certain block. We only use the keys since we just need the set of anchors, diff --git a/book/src/user/mining-testnet-s-nomp.md b/book/src/user/mining-testnet-s-nomp.md index 70fbc7a7647..fbffdb14d71 100644 --- a/book/src/user/mining-testnet-s-nomp.md +++ b/book/src/user/mining-testnet-s-nomp.md @@ -73,11 +73,11 @@ These fixes disable mining pool operator payments and miner payments: they just -2. [Build](https://github.com/ZcashFoundation/zebra#build-instructions) and [Run Zebra](https://zebra.zfnd.org/user/run.html) with the `getblocktemplate-rpcs` feature: +2. [Run Zebra](https://zebra.zfnd.org/user/run.html) with the config you created: ```sh - cargo run --release --features "getblocktemplate-rpcs" --bin zebrad -- -c zebrad.toml + zebrad -c zebrad.toml ``` -3. Wait a few hours for Zebra to sync to the testnet tip (on mainnet this takes 2-3 days) +3. Wait for Zebra to sync to the testnet tip. This takes 8-12 hours on testnet (or 2-3 days on mainnet) as of October 2023. ## Install `s-nomp` @@ -137,43 +137,49 @@ These fixes disable mining pool operator payments and miner payments: they just
Arch-specific instructions -#### Install dependencies +#### Install `s-nomp` -1. Install [`redis`](https://redis.io/docs/getting-started/) and run it on the default port: +1. Install Redis, and development libraries required by S-nomp ```sh - sudo pacman -S redis - sudo systemctl start redis + sudo pacman -S redis boost libsodium ``` - -2. Install and activate [`nvm`](https://github.com/nvm-sh/nvm#installing-and-updating): + +2. Install `nvm`, Python 3.10 and `virtualenv` ```sh - sudo pacman -S nvm - unset npm_config_prefix - source /usr/share/nvm/init-nvm.sh + paru -S python310 nvm + sudo pacman -S python-virtualenv ``` -3. Install `boost` and `libsodium` development libraries: - +3. Start Redis ```sh - sudo pacman -S boost libsodium + sudo systemctl start redis ``` -#### Install `s-nomp` +4. Clone the repository + + ```sh + git clone https://github.com/ZcashFoundation/s-nomp && cd s-nomp + ``` -1. `git clone https://github.com/ZcashFoundation/s-nomp && cd s-nomp` +5. Use Node 10: -2. Use the Zebra configs: `git checkout zebra-mining` + ```sh + unset npm_config_prefix + source /usr/share/nvm/init-nvm.sh + nvm install 10 + nvm use 10 + ``` -3. Use node 8.11.0: +6. Use Python 3.10 ```sh - nvm install 8.11.0 - nvm use 8.11.0 + virtualenv -p 3.10 s-nomp + source s-nomp/bin/activate ``` -4. Update dependencies and install: +7. Update dependencies and install: ```sh npm update diff --git a/book/src/user/supported-platforms.md b/book/src/user/supported-platforms.md index 152be56537e..d42246d091f 100644 --- a/book/src/user/supported-platforms.md +++ b/book/src/user/supported-platforms.md @@ -34,6 +34,7 @@ For the full requirements, see [Tier 2 platform policy](platform-tier-policy.md# | -------|-------|-------|-------|------- | `x86_64-unknown-linux-gnu` | [GitHub ubuntu-latest](https://github.com/actions/virtual-environments#available-environments) | 64-bit | [latest stable release](https://github.com/rust-lang/rust/releases) | N/A | `x86_64-unknown-linux-gnu` | [GitHub ubuntu-latest](https://github.com/actions/virtual-environments#available-environments) | 64-bit | [latest beta release](https://github.com/rust-lang/rust/blob/beta/src/version) | N/A +| `x86_64-apple-darwin` | [GitHub macos-latest](https://github.com/actions/virtual-environments#available-environments) | 64-bit | [latest stable release](https://github.com/rust-lang/rust/releases) | N/A ## Tier 3 @@ -46,5 +47,4 @@ For the full requirements, see [Tier 3 platform policy](platform-tier-policy.md# | platform | os | notes | rust | artifacts | -------|-------|-------|-------|------- | `aarch64-unknown-linux-gnu` | [Debian 11](https://www.debian.org/releases/bullseye/) | 64-bit | [latest stable release](https://github.com/rust-lang/rust/releases) | N/A -| `x86_64-apple-darwin` | [GitHub macos-latest](https://github.com/actions/virtual-environments#available-environments) | 64-bit | [latest stable release](https://github.com/rust-lang/rust/releases) | N/A - +| `aarch64-apple-darwin` | latest macOS | 64-bit, Apple M1 or M2 | [latest stable release](https://github.com/rust-lang/rust/releases) | N/A diff --git a/docker/Dockerfile b/docker/Dockerfile index 8966ff12c9a..a0a4b9a9466 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -95,9 +95,7 @@ ENV CARGO_HOME="/opt/zebrad/.cargo/" # We also download needed dependencies for tests to work, from other images. # An entrypoint.sh is only available in this step for easier test handling with variables. FROM deps AS tests -# TODO: do not hardcode the user /root/ even though is a safe assumption -# Pre-download Zcash Sprout, Sapling parameters and Lightwalletd binary -COPY --from=us-docker.pkg.dev/zfnd-dev-zebra/zebra/zcash-params:edge /root/.zcash-params /root/.zcash-params + COPY --from=us-docker.pkg.dev/zfnd-dev-zebra/zebra/lightwalletd:edge /opt/lightwalletd /usr/local/bin # cargo uses timestamps for its cache, so they need to be in this order: @@ -176,11 +174,10 @@ RUN chmod u+x /entrypoint.sh # This stage is only used when deploying nodes or when only the resulting zebrad binary is needed # # To save space, this step starts from scratch using debian, and only adds the resulting -# binary from the `release` stage, and the Zcash Sprout & Sapling parameters from ZCash +# binary from the `release` stage FROM debian:bullseye-slim AS runtime COPY --from=release /opt/zebrad/target/release/zebrad /usr/local/bin COPY --from=release /entrypoint.sh / -COPY --from=us-docker.pkg.dev/zfnd-dev-zebra/zebra/zcash-params:edge /root/.zcash-params /root/.zcash-params RUN apt-get update && \ apt-get install -y --no-install-recommends \ diff --git a/docker/zcash-params/Dockerfile b/docker/zcash-params/Dockerfile deleted file mode 100644 index dce8153d185..00000000000 --- a/docker/zcash-params/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -# This image is for caching Zcash Sprout and Sapling parameters. -# We don't test it automatically in CI due to download server rate-limiting. -# To manually run it on the PR branch before merging, go to: -# https://github.com/ZcashFoundation/zebra/actions/workflows/zcash-params.yml - -FROM debian:bullseye-slim AS release - -# Just use the precompiled zebrad binary from a recent release image. -# -# It doesn't matter what build or commit of Zebra we use, because it just calls into the -# zcash_proofs download code. (Which doesn't change much.) -# Test image zebrad binaries would also work, but it's harder to get a recent tag for them. -# -# Compiling the download-params example using `cargo ` is another alternative: -# `cargo run --locked --release --features default-docker --example download-params` -COPY --from=zfnd/zebra:latest /usr/local/bin/zebrad /usr/local/bin - -# Pre-download Zcash Sprout and Sapling parameters -RUN zebrad download diff --git a/zebrad/src/commands.rs b/zebrad/src/commands.rs index d7f4fa337be..70728ce9302 100644 --- a/zebrad/src/commands.rs +++ b/zebrad/src/commands.rs @@ -1,7 +1,16 @@ //! Zebrad Subcommands +use std::path::PathBuf; + +use abscissa_core::{config::Override, Command, Configurable, FrameworkError, Runnable}; + +use crate::config::ZebradConfig; + +pub use self::{entry_point::EntryPoint, start::StartCmd}; + +use self::{copy_state::CopyStateCmd, generate::GenerateCmd, tip_height::TipHeightCmd}; + mod copy_state; -mod download; mod entry_point; mod generate; mod start; @@ -10,18 +19,7 @@ mod tip_height; #[cfg(test)] mod tests; -use self::ZebradCmd::*; -use self::{ - copy_state::CopyStateCmd, download::DownloadCmd, generate::GenerateCmd, - tip_height::TipHeightCmd, -}; - -pub use self::{entry_point::EntryPoint, start::StartCmd}; - -use crate::config::ZebradConfig; - -use abscissa_core::{config::Override, Command, Configurable, FrameworkError, Runnable}; -use std::path::PathBuf; +use ZebradCmd::*; /// Zebrad Configuration Filename pub const CONFIG_FILE: &str = "zebrad.toml"; @@ -33,10 +31,6 @@ pub enum ZebradCmd { // TODO: hide this command from users in release builds (#3279) CopyState(CopyStateCmd), - // The `download` subcommand - /// Pre-download required Zcash Sprout and Sapling parameter files - Download(DownloadCmd), - /// Generate a default `zebrad.toml` configuration Generate(GenerateCmd), @@ -60,7 +54,7 @@ impl ZebradCmd { CopyState(_) | Start(_) => true, // Utility commands that don't use server components - Download(_) | Generate(_) | TipHeight(_) => false, + Generate(_) | TipHeight(_) => false, } } @@ -74,14 +68,14 @@ impl ZebradCmd { Start(_) => true, // Utility commands - CopyState(_) | Download(_) | Generate(_) | TipHeight(_) => false, + CopyState(_) | Generate(_) | TipHeight(_) => false, } } /// Returns true if this command should ignore errors when /// attempting to load a config file. pub(crate) fn should_ignore_load_config_error(&self) -> bool { - matches!(self, ZebradCmd::Generate(_) | ZebradCmd::Download(_)) + matches!(self, ZebradCmd::Generate(_)) } /// Returns the default log level for this command, based on the `verbose` command line flag. @@ -96,7 +90,7 @@ impl ZebradCmd { Generate(_) | TipHeight(_) => true, // Commands that generate informative logging output by default. - CopyState(_) | Download(_) | Start(_) => false, + CopyState(_) | Start(_) => false, }; if only_show_warnings && !verbose { @@ -113,7 +107,6 @@ impl Runnable for ZebradCmd { fn run(&self) { match self { CopyState(cmd) => cmd.run(), - Download(cmd) => cmd.run(), Generate(cmd) => cmd.run(), Start(cmd) => cmd.run(), TipHeight(cmd) => cmd.run(), diff --git a/zebrad/src/commands/download.rs b/zebrad/src/commands/download.rs deleted file mode 100644 index 4feefcb9e58..00000000000 --- a/zebrad/src/commands/download.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! `download` subcommand - pre-download required parameter files -//! -//! `zebrad download` automatically downloads required parameter files the first time it is run. -//! -//! This command should be used if you're launching lots of `zebrad start` instances for testing, -//! or you want to include the parameter files in a distribution package. - -use abscissa_core::{Command, Runnable}; - -/// Pre-download required Zcash Sprout and Sapling parameter files -#[derive(Command, Debug, Default, clap::Parser)] -pub struct DownloadCmd {} - -impl DownloadCmd { - /// Download the Sapling and Sprout Groth16 parameters if needed, - /// check they were downloaded correctly, and load them into Zebra. - /// - /// # Panics - /// - /// If the downloaded or pre-existing parameter files are invalid. - fn download_and_check(&self) { - // The lazy static initializer does the download, if needed, - // and the file hash checks. - lazy_static::initialize(&zebra_consensus::groth16::GROTH16_PARAMETERS); - } -} - -impl Runnable for DownloadCmd { - /// Run the download command. - fn run(&self) { - info!("checking if Zcash Sapling and Sprout parameters have been downloaded"); - - self.download_and_check(); - } -}