forest/tool/subcommands/
fetch_params_cmd.rs

1// Copyright 2019-2025 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use std::path::PathBuf;
5
6use crate::shim::sector::SectorSize;
7use crate::utils::proofs_api::{SectorSizeOpt, get_params_default};
8
9use crate::cli::subcommands::cli_error_and_die;
10use crate::cli_shared::read_config;
11
12#[allow(missing_docs)]
13#[derive(Debug, clap::Args)]
14pub struct FetchCommands {
15    /// Download all proof parameters
16    #[arg(short, long)]
17    all: bool,
18    /// Download only verification keys
19    #[arg(short, long)]
20    keys: bool,
21    /// Print out download location instead of downloading files
22    #[arg(short, long)]
23    dry_run: bool,
24    /// Size in bytes
25    params_size: Option<String>,
26    /// Optional TOML file containing forest daemon configuration
27    #[arg(short, long)]
28    pub config: Option<PathBuf>,
29}
30
31impl FetchCommands {
32    pub async fn run(self) -> anyhow::Result<()> {
33        let (_, config) = read_config(self.config.as_ref(), None)?;
34
35        let sizes = if self.all {
36            SectorSizeOpt::All
37        } else if let Some(size) = &self.params_size {
38            let sector_size = ram_to_int(size)?;
39            SectorSizeOpt::Size(sector_size)
40        } else if self.keys {
41            SectorSizeOpt::Keys
42        } else {
43            cli_error_and_die(
44                "Sector size option must be chosen. Choose between --all, --keys, or <size>",
45                1,
46            );
47        };
48
49        get_params_default(&config.client.data_dir, sizes, self.dry_run).await
50    }
51}
52
53/// Converts a human readable string to a `u64` size.
54fn ram_to_int(size: &str) -> anyhow::Result<SectorSize> {
55    // * there is no library to do this, but if other sector sizes are supported in
56    //   future
57    // this should probably be changed to parse from string to `SectorSize`
58    let size = size.to_lowercase();
59    let trimmed = size.trim_end_matches('b');
60
61    type SectorSize = crate::shim::sector::SectorSize;
62
63    match trimmed {
64        "2048" | "2ki" => Ok(SectorSize::_2KiB),
65        "8388608" | "8mi" => Ok(SectorSize::_8MiB),
66        "536870912" | "512mi" => Ok(SectorSize::_512MiB),
67        "34359738368" | "32gi" => Ok(SectorSize::_32GiB),
68        "68719476736" | "64gi" => Ok(SectorSize::_64GiB),
69        _ => Err(anyhow::Error::msg(format!(
70            "Failed to parse: {size}. Must be a valid sector size"
71        ))),
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    type SectorSize = crate::shim::sector::SectorSize;
80
81    #[test]
82    fn ram_str_conversions() {
83        assert_eq!(ram_to_int("2048").unwrap(), SectorSize::_2KiB);
84        assert_eq!(ram_to_int("2048B").unwrap(), SectorSize::_2KiB);
85        assert_eq!(ram_to_int("2kib").unwrap(), SectorSize::_2KiB);
86        assert_eq!(ram_to_int("8Mib").unwrap(), SectorSize::_8MiB);
87        assert_eq!(ram_to_int("512MiB").unwrap(), SectorSize::_512MiB);
88        assert_eq!(ram_to_int("32Gi").unwrap(), SectorSize::_32GiB);
89        assert_eq!(ram_to_int("32GiB").unwrap(), SectorSize::_32GiB);
90        assert_eq!(ram_to_int("64Gib").unwrap(), SectorSize::_64GiB);
91    }
92}