1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::any::TypeId;
use std::env;

use config::{Config, ConfigError, Environment, File};
use filecoin_hashers::poseidon::PoseidonHasher;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};

use crate::merkle::MerkleTreeTrait;

lazy_static! {
    pub static ref SETTINGS: Settings = Settings::new().expect("invalid configuration");
}

const SETTINGS_PATH: &str = "./rust-fil-proofs.config.toml";
const PREFIX: &str = "FIL_PROOFS";
pub const DEFAULT_ROWS_TO_DISCARD: u32 = 2;

#[derive(Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct Settings {
    pub verify_cache: bool,
    pub verify_production_params: bool,
    pub use_gpu_column_builder: bool,
    pub max_gpu_column_batch_size: u32,
    pub column_write_batch_size: u32,
    pub use_gpu_tree_builder: bool,
    pub max_gpu_tree_batch_size: u32,
    pub rows_to_discard: u32,
    pub sdr_parents_cache_size: u32,
    pub window_post_synthesis_num_cpus: u32,
    pub parameter_cache: String,
    pub parent_cache: String,
    pub use_multicore_sdr: bool,
    pub multicore_sdr_producers: usize,
    pub multicore_sdr_producer_stride: u64,
    pub multicore_sdr_lookahead: usize,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            verify_cache: false,
            verify_production_params: false,
            use_gpu_column_builder: false,
            max_gpu_column_batch_size: 400_000,
            column_write_batch_size: 262_144,
            use_gpu_tree_builder: false,
            max_gpu_tree_batch_size: 700_000,
            rows_to_discard: DEFAULT_ROWS_TO_DISCARD,
            sdr_parents_cache_size: 2_048,
            window_post_synthesis_num_cpus: num_cpus::get() as u32,
            // `parameter_cache` does not use the cache() mechanism because it is now used
            // for durable, canonical Groth parameters and verifying keys.
            // The name is retained for backwards compatibility.
            parameter_cache: "/var/tmp/filecoin-proof-parameters/".to_string(),
            parent_cache: cache("filecoin-parents"),
            use_multicore_sdr: false,
            multicore_sdr_producers: 3,
            multicore_sdr_producer_stride: 128,
            multicore_sdr_lookahead: 800,
        }
    }
}

/// All cache files and directories paths should be constructed using this function,
/// which its base directory from the FIL_PROOFS_CACHE_DIR env var, and defaults to /var/tmp.
/// Note that FIL_PROOFS_CACHE_DIR is not a first class setting and can only be set by env var.
fn cache(s: &str) -> String {
    let cache_var = format!("{}_CACHE_DIR", PREFIX);
    let mut cache_name = env::var(cache_var).unwrap_or_else(|_| "/var/tmp/".to_string());
    cache_name.push_str(s);
    cache_name
}

/// Sets an environment variable to a value if it isn't properly set yet.
fn set_env_var_if_unset(env_var: &str, value: &str) {
    if env::var(env_var).is_err() {
        env::set_var(env_var, value);
    }
}

/// Set the GPU framework for the dependencies.
///
/// If a GPU framework, CUDA and OpenCL is selected, it needs to be communicated some of the
/// dependnecies. This is done via environment variables.
///
/// If one of those environment variables is already set, it won't be overridden.
fn set_gpu_framework() {
    if let Ok(framework) = env::var(format!("{}_GPU_FRAMEWORK", PREFIX)) {
        set_env_var_if_unset("BELLMAN_GPU_FRAMEWORK", &framework);
        set_env_var_if_unset("NEPTUNE_GPU_FRAMEWORK", &framework);
    }
}

impl Settings {
    fn new() -> Result<Settings, ConfigError> {
        set_gpu_framework();

        Config::builder()
            .add_source(File::with_name(SETTINGS_PATH).required(false))
            .add_source(Environment::with_prefix(PREFIX))
            .build()?
            .try_deserialize()
    }

    // Even if the column builder is enabled, the GPU column builder
    // only supports Poseidon hashes.
    pub fn use_gpu_column_builder<Tree: MerkleTreeTrait>(&self) -> bool {
        self.use_gpu_tree_builder && TypeId::of::<Tree::Hasher>() == TypeId::of::<PoseidonHasher>()
    }

    // Even if the tree builder is enabled, the GPU tree builder
    // only supports Poseidon hashes.
    pub fn use_gpu_tree_builder<Tree: MerkleTreeTrait>(&self) -> bool {
        self.use_gpu_tree_builder && TypeId::of::<Tree::Hasher>() == TypeId::of::<PoseidonHasher>()
    }
}