Skip to main content

dfx_core/config/model/
replica_config.rs

1use crate::config::model::dfinity::{ReplicaLogLevel, ReplicaSubnetType};
2use candid::Principal;
3use serde::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::default::Default;
6use std::path::{Path, PathBuf};
7
8#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
9pub struct HttpHandlerConfig {
10    /// Instructs the HTTP handler to use the specified port
11    pub port: Option<u16>,
12
13    /// Instructs the HTTP handler to bind to any open port and report the port
14    /// to the specified file.
15    /// The port is written in its textual representation, no newline at the
16    /// end.
17    pub write_port_to: Option<PathBuf>,
18}
19
20#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
21pub struct BtcAdapterConfig {
22    pub enabled: bool,
23    pub socket_path: Option<PathBuf>,
24}
25
26#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
27pub struct CanisterHttpAdapterConfig {
28    pub enabled: bool,
29    pub socket_path: Option<PathBuf>,
30}
31
32#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
33pub struct ArtifactPoolConfig {
34    pub consensus_pool_path: PathBuf,
35}
36
37#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
38pub struct CryptoConfig {
39    pub crypto_root: PathBuf,
40}
41
42#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
43pub struct StateManagerConfig {
44    pub state_root: PathBuf,
45}
46
47#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
48pub struct ReplicaConfig {
49    pub http_handler: HttpHandlerConfig,
50    pub state_manager: StateManagerConfig,
51    pub crypto: CryptoConfig,
52    pub artifact_pool: ArtifactPoolConfig,
53    pub subnet_type: ReplicaSubnetType,
54    pub btc_adapter: BtcAdapterConfig,
55    pub canister_http_adapter: CanisterHttpAdapterConfig,
56    pub log_level: ReplicaLogLevel,
57    pub artificial_delay: u32,
58    pub system_canisters: bool,
59}
60
61impl ReplicaConfig {
62    pub fn new(
63        state_root: &Path,
64        subnet_type: ReplicaSubnetType,
65        log_level: ReplicaLogLevel,
66        artificial_delay: u32,
67    ) -> Self {
68        ReplicaConfig {
69            http_handler: HttpHandlerConfig {
70                write_port_to: None,
71                port: None,
72            },
73            state_manager: StateManagerConfig {
74                state_root: state_root.join("replicated_state"),
75            },
76            crypto: CryptoConfig {
77                crypto_root: state_root.join("crypto_store"),
78            },
79            artifact_pool: ArtifactPoolConfig {
80                consensus_pool_path: state_root.join("consensus_pool"),
81            },
82            subnet_type,
83            btc_adapter: BtcAdapterConfig {
84                enabled: false,
85                socket_path: None,
86            },
87            canister_http_adapter: CanisterHttpAdapterConfig {
88                enabled: false,
89                socket_path: None,
90            },
91            log_level,
92            artificial_delay,
93            system_canisters: false,
94        }
95    }
96
97    pub fn with_port(self, port: u16) -> Self {
98        ReplicaConfig {
99            http_handler: self.http_handler.with_port(port),
100            ..self
101        }
102    }
103
104    pub fn with_random_port(self, write_port_to: &Path) -> Self {
105        ReplicaConfig {
106            http_handler: self.http_handler.with_random_port(write_port_to),
107            ..self
108        }
109    }
110
111    pub fn with_btc_adapter_enabled(self) -> Self {
112        ReplicaConfig {
113            btc_adapter: self.btc_adapter.with_enabled(),
114            ..self
115        }
116    }
117
118    pub fn with_btc_adapter_socket(self, socket_path: PathBuf) -> Self {
119        ReplicaConfig {
120            btc_adapter: self.btc_adapter.with_socket_path(socket_path),
121            ..self
122        }
123    }
124
125    pub fn with_canister_http_adapter_enabled(self) -> Self {
126        ReplicaConfig {
127            canister_http_adapter: self.canister_http_adapter.with_enabled(),
128            ..self
129        }
130    }
131    pub fn with_canister_http_adapter_socket(self, socket_path: PathBuf) -> Self {
132        ReplicaConfig {
133            canister_http_adapter: self.canister_http_adapter.with_socket_path(socket_path),
134            ..self
135        }
136    }
137
138    pub fn with_system_canisters(self) -> Self {
139        ReplicaConfig {
140            system_canisters: true,
141            ..self
142        }
143    }
144}
145
146impl BtcAdapterConfig {
147    pub fn with_enabled(self) -> Self {
148        BtcAdapterConfig {
149            enabled: true,
150            ..self
151        }
152    }
153
154    pub fn with_socket_path(self, socket_path: PathBuf) -> Self {
155        BtcAdapterConfig {
156            socket_path: Some(socket_path),
157            ..self
158        }
159    }
160}
161
162impl CanisterHttpAdapterConfig {
163    pub fn with_enabled(self) -> Self {
164        CanisterHttpAdapterConfig {
165            enabled: true,
166            ..self
167        }
168    }
169
170    pub fn with_socket_path(self, socket_path: PathBuf) -> Self {
171        CanisterHttpAdapterConfig {
172            socket_path: Some(socket_path),
173            ..self
174        }
175    }
176}
177
178impl HttpHandlerConfig {
179    pub fn with_port(self, port: u16) -> Self {
180        HttpHandlerConfig {
181            port: Some(port),
182            write_port_to: None,
183        }
184    }
185
186    pub fn with_random_port(self, write_port_to: &Path) -> Self {
187        HttpHandlerConfig {
188            port: None,
189            write_port_to: Some(write_port_to.to_path_buf()),
190        }
191    }
192}
193
194#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
195#[serde(tag = "type", rename_all = "snake_case")]
196#[allow(clippy::large_enum_variant)]
197pub enum CachedReplicaConfig<'a> {
198    Replica { config: Cow<'a, ReplicaConfig> },
199    PocketIc { config: Cow<'a, ReplicaConfig> },
200}
201
202#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
203pub struct CachedConfig<'a> {
204    pub replica_rev: String,
205    pub effective_canister_id: Option<Principal>,
206    #[serde(flatten)]
207    pub config: CachedReplicaConfig<'a>,
208}
209
210impl<'a> CachedConfig<'a> {
211    pub fn replica(config: &'a ReplicaConfig, replica_rev: String) -> Self {
212        Self {
213            replica_rev,
214            effective_canister_id: None,
215            config: CachedReplicaConfig::Replica {
216                config: Cow::Borrowed(config),
217            },
218        }
219    }
220    pub fn pocketic(
221        config: &'a ReplicaConfig,
222        replica_rev: String,
223        effective_canister_id: Option<Principal>,
224    ) -> Self {
225        Self {
226            replica_rev,
227            effective_canister_id,
228            config: CachedReplicaConfig::PocketIc {
229                config: Cow::Borrowed(config),
230            },
231        }
232    }
233    pub fn can_share_state(&self, other: &Self) -> bool {
234        // effective canister id does not matter for ability to share state
235        self.replica_rev == other.replica_rev && self.config == other.config
236    }
237    pub fn get_effective_canister_id(&self) -> Option<Principal> {
238        self.effective_canister_id
239    }
240}