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#[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
139lazy_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}