node/
config.rs

1use std::{str::FromStr, sync::Arc};
2
3use mina_p2p_messages::v2::CurrencyFeeStableV1;
4use openmina_core::consensus::ConsensusConstants;
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}
39
40#[derive(Serialize, Deserialize, Debug, Clone)]
41pub struct SnarkerConfig {
42    pub public_key: AccountPublicKey,
43    pub fee: CurrencyFeeStableV1,
44    pub strategy: SnarkerStrategy,
45    pub auto_commit: bool,
46}
47
48#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
49pub enum SnarkerStrategy {
50    Sequential,
51    Random,
52}
53
54#[derive(Serialize, Deserialize, Debug, Clone)]
55pub struct BuildEnv {
56    pub time: String,
57    pub version: String,
58    pub git: GitBuildEnv,
59    pub cargo: CargoBuildEnv,
60    pub rustc: RustCBuildEnv,
61}
62
63#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
64pub struct GitBuildEnv {
65    pub commit_time: String,
66    pub commit_hash: String,
67    pub branch: String,
68}
69
70#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
71pub struct CargoBuildEnv {
72    pub features: String,
73    pub opt_level: u8,
74    pub target: String,
75    pub is_debug: bool,
76}
77
78#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
79pub struct RustCBuildEnv {
80    pub channel: String,
81    pub commit_date: String,
82    pub commit_hash: String,
83    pub host: String,
84    pub version: String,
85    pub llvm_version: String,
86}
87
88#[allow(clippy::eq_op)]
89impl BuildEnv {
90    pub fn get() -> Self {
91        Self {
92            time: env!("VERGEN_BUILD_TIMESTAMP").to_owned(),
93            version: env!("VERGEN_GIT_DESCRIBE").to_owned(),
94            git: GitBuildEnv {
95                commit_time: env!("VERGEN_GIT_COMMIT_TIMESTAMP").to_owned(),
96                commit_hash: env!("VERGEN_GIT_SHA").to_owned(),
97                branch: env!("VERGEN_GIT_BRANCH").to_owned(),
98            },
99            cargo: CargoBuildEnv {
100                features: env!("VERGEN_CARGO_FEATURES").to_owned(),
101                opt_level: env!("VERGEN_CARGO_OPT_LEVEL").parse().unwrap(),
102                target: env!("VERGEN_CARGO_TARGET_TRIPLE").to_owned(),
103                is_debug: env!("VERGEN_CARGO_DEBUG") == "true",
104            },
105            rustc: RustCBuildEnv {
106                channel: env!("VERGEN_RUSTC_CHANNEL").to_owned(),
107                commit_date: env!("VERGEN_RUSTC_COMMIT_DATE").to_owned(),
108                commit_hash: env!("VERGEN_RUSTC_COMMIT_HASH").to_owned(),
109                host: env!("VERGEN_RUSTC_HOST_TRIPLE").to_owned(),
110                version: env!("VERGEN_RUSTC_SEMVER").to_owned(),
111                llvm_version: env!("VERGEN_RUSTC_LLVM_VERSION").to_owned(),
112            },
113        }
114    }
115}
116
117#[derive(thiserror::Error, Debug)]
118#[error("invalid strategy: {0}! expected one of: seq/sequential/rand/random")]
119pub struct SnarkerStrategyParseError(String);
120
121impl FromStr for SnarkerStrategy {
122    type Err = SnarkerStrategyParseError;
123
124    fn from_str(s: &str) -> Result<Self, Self::Err> {
125        Ok(match s {
126            "seq" | "sequential" => SnarkerStrategy::Sequential,
127            "rand" | "random" => SnarkerStrategy::Random,
128            other => return Err(SnarkerStrategyParseError(other.to_owned())),
129        })
130    }
131}
132
133// Load static devnet genesis ledger for testing
134lazy_static::lazy_static! {
135    pub static ref DEVNET_CONFIG: Arc<GenesisConfig> = {
136        let bytes = include_bytes!("../../genesis_ledgers/devnet.bin");
137        Arc::new(GenesisConfig::Prebuilt(
138            std::borrow::Cow::Borrowed(bytes)
139        ))
140    };
141}
142
143#[cfg(test)]
144mod tests {
145    use time::{format_description::well_known::Rfc3339, OffsetDateTime};
146
147    use super::DEVNET_CONFIG;
148
149    #[test]
150    fn devnet_config() {
151        let (_mask, config) = DEVNET_CONFIG.load().expect("should be loadable");
152
153        assert_eq!(
154            config.genesis_ledger_hash,
155            "jy1wjiJgTkzXr7yL8r5x4ikaNJuikibsRMnkjdH6uqGCsDmR2sf"
156                .parse()
157                .unwrap()
158        );
159        assert_eq!(
160            config.constants.genesis_state_timestamp,
161            OffsetDateTime::parse("2024-04-09T21:00:00Z", &Rfc3339)
162                .unwrap()
163                .into()
164        );
165    }
166}