Skip to main content

mina_node/
config.rs

1use std::{str::FromStr, sync::Arc};
2
3use mina_core::consensus::ConsensusConstants;
4use mina_p2p_messages::v2::CurrencyFeeStableV1;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8    account::AccountPublicKey,
9    transition_frontier::{archive::archive_config::ArchiveConfig, genesis::GenesisConfig},
10};
11pub use crate::{
12    block_producer::BlockProducerConfig, ledger::LedgerConfig, p2p::P2pConfig, snark::SnarkConfig,
13    snark_pool::SnarkPoolConfig, transition_frontier::TransitionFrontierConfig,
14};
15pub use mina_p2p_messages::v2::MinaBaseProtocolConstantsCheckedValueStableV1 as ProtocolConstants;
16
17// TODO(binier): maybe make sure config is immutable.
18
19#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct Config {
21    pub ledger: LedgerConfig,
22    pub snark: SnarkConfig,
23    pub p2p: P2pConfig,
24    pub transition_frontier: TransitionFrontierConfig,
25    pub archive: Option<ArchiveConfig>,
26    pub block_producer: Option<BlockProducerConfig>,
27    pub global: GlobalConfig,
28    pub tx_pool: ledger::transaction_pool::Config,
29}
30
31#[derive(Serialize, Deserialize, Debug, Clone)]
32pub struct GlobalConfig {
33    pub build: Box<BuildEnv>,
34    pub snarker: Option<SnarkerConfig>,
35    pub consensus_constants: ConsensusConstants,
36    pub client_port: Option<u16>,
37    pub testing_run: bool,
38    pub chain_id_override: Option<mina_core::ChainId>,
39    pub skip_proof_verification: bool,
40}
41
42#[derive(Serialize, Deserialize, Debug, Clone)]
43pub struct SnarkerConfig {
44    pub public_key: AccountPublicKey,
45    pub fee: CurrencyFeeStableV1,
46    pub strategy: SnarkerStrategy,
47    pub auto_commit: bool,
48}
49
50#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
51pub enum SnarkerStrategy {
52    Sequential,
53    Random,
54}
55
56#[derive(Serialize, Deserialize, Debug, Clone)]
57#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
58pub struct BuildEnv {
59    pub time: String,
60    pub version: String,
61    pub git: GitBuildEnv,
62    pub cargo: CargoBuildEnv,
63    pub rustc: RustCBuildEnv,
64}
65
66#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
67#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
68pub struct GitBuildEnv {
69    pub commit_time: String,
70    pub commit_hash: String,
71    pub branch: String,
72}
73
74#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
75#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
76pub struct CargoBuildEnv {
77    pub features: String,
78    pub opt_level: u8,
79    pub target: String,
80    pub is_debug: bool,
81}
82
83#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
84#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
85pub struct RustCBuildEnv {
86    pub channel: String,
87    pub commit_date: String,
88    pub commit_hash: String,
89    pub host: String,
90    pub version: String,
91    pub llvm_version: String,
92}
93
94#[allow(clippy::eq_op)]
95impl BuildEnv {
96    pub fn get() -> Self {
97        Self {
98            time: env!("VERGEN_BUILD_TIMESTAMP").to_owned(),
99            version: env!("VERGEN_GIT_DESCRIBE").to_owned(),
100            git: GitBuildEnv {
101                commit_time: env!("VERGEN_GIT_COMMIT_TIMESTAMP").to_owned(),
102                commit_hash: env!("VERGEN_GIT_SHA").to_owned(),
103                branch: env!("VERGEN_GIT_BRANCH").to_owned(),
104            },
105            cargo: CargoBuildEnv {
106                features: env!("VERGEN_CARGO_FEATURES").to_owned(),
107                opt_level: env!("VERGEN_CARGO_OPT_LEVEL").parse().unwrap(),
108                target: env!("VERGEN_CARGO_TARGET_TRIPLE").to_owned(),
109                is_debug: env!("VERGEN_CARGO_DEBUG") == "true",
110            },
111            rustc: RustCBuildEnv {
112                channel: env!("VERGEN_RUSTC_CHANNEL").to_owned(),
113                commit_date: env!("VERGEN_RUSTC_COMMIT_DATE").to_owned(),
114                commit_hash: env!("VERGEN_RUSTC_COMMIT_HASH").to_owned(),
115                host: env!("VERGEN_RUSTC_HOST_TRIPLE").to_owned(),
116                version: env!("VERGEN_RUSTC_SEMVER").to_owned(),
117                llvm_version: env!("VERGEN_RUSTC_LLVM_VERSION").to_owned(),
118            },
119        }
120    }
121}
122
123#[derive(thiserror::Error, Debug)]
124#[error("invalid strategy: {0}! expected one of: seq/sequential/rand/random")]
125pub struct SnarkerStrategyParseError(String);
126
127impl FromStr for SnarkerStrategy {
128    type Err = SnarkerStrategyParseError;
129
130    fn from_str(s: &str) -> Result<Self, Self::Err> {
131        Ok(match s {
132            "seq" | "sequential" => SnarkerStrategy::Sequential,
133            "rand" | "random" => SnarkerStrategy::Random,
134            other => return Err(SnarkerStrategyParseError(other.to_owned())),
135        })
136    }
137}
138
139// Load static devnet genesis ledger for testing
140lazy_static::lazy_static! {
141    pub static ref DEVNET_CONFIG: Arc<GenesisConfig> = {
142        let bytes = include_bytes!("../../../genesis_ledgers/devnet.bin");
143        Arc::new(GenesisConfig::Prebuilt(
144            std::borrow::Cow::Borrowed(bytes)
145        ))
146    };
147}
148
149#[cfg(test)]
150mod tests {
151    use time::{format_description::well_known::Rfc3339, OffsetDateTime};
152
153    use super::DEVNET_CONFIG;
154
155    #[test]
156    fn devnet_config() {
157        let (_mask, config) = DEVNET_CONFIG.load().expect("should be loadable");
158
159        assert_eq!(
160            config.genesis_ledger_hash,
161            "jy1wjiJgTkzXr7yL8r5x4ikaNJuikibsRMnkjdH6uqGCsDmR2sf"
162                .parse()
163                .unwrap()
164        );
165        assert_eq!(
166            config.constants.genesis_state_timestamp,
167            OffsetDateTime::parse("2024-04-09T21:00:00Z", &Rfc3339)
168                .unwrap()
169                .into()
170        );
171    }
172}