1#![allow(clippy::pedantic)]
3
4use std::collections::BTreeMap;
5use std::marker;
6use std::marker::PhantomData;
7use std::sync::Arc;
8
9use fedimint_api_client::api::DynModuleApi;
10use fedimint_core::config::{
11 ClientModuleConfig, CommonModuleInitRegistry, ConfigGenModuleParams, ModuleInitParams,
12 ModuleInitRegistry, ServerModuleConfig, ServerModuleConsensusConfig,
13};
14use fedimint_core::core::{ModuleInstanceId, ModuleKind};
15use fedimint_core::db::{CoreMigrationFn, Database, DatabaseVersion};
16use fedimint_core::module::{
17 CommonModuleInit, CoreConsensusVersion, IDynCommonModuleInit, ModuleConsensusVersion,
18 ModuleInit, PeerHandle, SupportedModuleApiVersions,
19};
20use fedimint_core::task::TaskGroup;
21use fedimint_core::{apply, async_trait_maybe_send, dyn_newtype_define, NumPeers, PeerId};
22
23use crate::DynServerModule;
24
25#[apply(async_trait_maybe_send!)]
35pub trait IServerModuleInit: IDynCommonModuleInit {
36 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static);
37
38 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
39
40 async fn init(
42 &self,
43 peer_num: NumPeers,
44 cfg: ServerModuleConfig,
45 db: Database,
46 task_group: &TaskGroup,
47 our_peer_id: PeerId,
48 module_api: DynModuleApi,
49 ) -> anyhow::Result<DynServerModule>;
50
51 fn validate_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<()>;
52
53 fn trusted_dealer_gen(
54 &self,
55 peers: &[PeerId],
56 params: &ConfigGenModuleParams,
57 ) -> BTreeMap<PeerId, ServerModuleConfig>;
58
59 async fn distributed_gen(
60 &self,
61 peers: &PeerHandle,
62 params: &ConfigGenModuleParams,
63 ) -> anyhow::Result<ServerModuleConfig>;
64
65 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
66
67 fn get_client_config(
68 &self,
69 module_instance_id: ModuleInstanceId,
70 config: &ServerModuleConsensusConfig,
71 ) -> anyhow::Result<ClientModuleConfig>;
72
73 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, CoreMigrationFn>;
77}
78
79pub struct ServerModuleInitArgs<S>
80where
81 S: ServerModuleInit,
82{
83 cfg: ServerModuleConfig,
84 db: Database,
85 task_group: TaskGroup,
86 our_peer_id: PeerId,
87 num_peers: NumPeers,
88 module_api: DynModuleApi,
89 _marker: marker::PhantomData<S>,
92}
93
94impl<S> ServerModuleInitArgs<S>
95where
96 S: ServerModuleInit,
97{
98 pub fn cfg(&self) -> &ServerModuleConfig {
99 &self.cfg
100 }
101
102 pub fn db(&self) -> &Database {
103 &self.db
104 }
105
106 pub fn num_peers(&self) -> NumPeers {
107 self.num_peers
108 }
109
110 pub fn task_group(&self) -> &TaskGroup {
111 &self.task_group
112 }
113
114 pub fn our_peer_id(&self) -> PeerId {
115 self.our_peer_id
116 }
117
118 pub fn module_api(&self) -> &DynModuleApi {
119 &self.module_api
120 }
121}
122#[apply(async_trait_maybe_send!)]
129pub trait ServerModuleInit: ModuleInit + Sized {
130 type Params: ModuleInitParams;
131
132 fn versions(&self, core: CoreConsensusVersion) -> &[ModuleConsensusVersion];
145
146 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
147
148 fn kind() -> ModuleKind {
149 <Self as ModuleInit>::Common::KIND
150 }
151
152 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<DynServerModule>;
154
155 fn parse_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<Self::Params> {
156 params.to_typed::<Self::Params>()
157 }
158
159 fn trusted_dealer_gen(
160 &self,
161 peers: &[PeerId],
162 params: &ConfigGenModuleParams,
163 ) -> BTreeMap<PeerId, ServerModuleConfig>;
164
165 async fn distributed_gen(
166 &self,
167 peer: &PeerHandle,
168 params: &ConfigGenModuleParams,
169 ) -> anyhow::Result<ServerModuleConfig>;
170
171 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
172
173 fn get_client_config(
175 &self,
176 config: &ServerModuleConsensusConfig,
177 ) -> anyhow::Result<<<Self as ModuleInit>::Common as CommonModuleInit>::ClientConfig>;
178
179 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, CoreMigrationFn> {
183 BTreeMap::new()
184 }
185}
186
187#[apply(async_trait_maybe_send!)]
188impl<T> IServerModuleInit for T
189where
190 T: ServerModuleInit + 'static + Sync,
191{
192 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
193 self
194 }
195
196 fn supported_api_versions(&self) -> SupportedModuleApiVersions {
197 <Self as ServerModuleInit>::supported_api_versions(self)
198 }
199
200 async fn init(
201 &self,
202 num_peers: NumPeers,
203 cfg: ServerModuleConfig,
204 db: Database,
205 task_group: &TaskGroup,
206 our_peer_id: PeerId,
207 module_api: DynModuleApi,
208 ) -> anyhow::Result<DynServerModule> {
209 <Self as ServerModuleInit>::init(
210 self,
211 &ServerModuleInitArgs {
212 num_peers,
213 cfg,
214 db,
215 task_group: task_group.clone(),
216 our_peer_id,
217 _marker: PhantomData,
218 module_api,
219 },
220 )
221 .await
222 }
223
224 fn validate_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<()> {
225 <Self as ServerModuleInit>::parse_params(self, params)?;
226 Ok(())
227 }
228
229 fn trusted_dealer_gen(
230 &self,
231 peers: &[PeerId],
232 params: &ConfigGenModuleParams,
233 ) -> BTreeMap<PeerId, ServerModuleConfig> {
234 <Self as ServerModuleInit>::trusted_dealer_gen(self, peers, params)
235 }
236
237 async fn distributed_gen(
238 &self,
239 peers: &PeerHandle,
240 params: &ConfigGenModuleParams,
241 ) -> anyhow::Result<ServerModuleConfig> {
242 <Self as ServerModuleInit>::distributed_gen(self, peers, params).await
243 }
244
245 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()> {
246 <Self as ServerModuleInit>::validate_config(self, identity, config)
247 }
248
249 fn get_client_config(
250 &self,
251 module_instance_id: ModuleInstanceId,
252 config: &ServerModuleConsensusConfig,
253 ) -> anyhow::Result<ClientModuleConfig> {
254 ClientModuleConfig::from_typed(
255 module_instance_id,
256 <Self as ServerModuleInit>::kind(),
257 config.version,
258 <Self as ServerModuleInit>::get_client_config(self, config)?,
259 )
260 }
261
262 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, CoreMigrationFn> {
263 <Self as ServerModuleInit>::get_database_migrations(self)
264 }
265}
266
267dyn_newtype_define!(
268 #[derive(Clone)]
269 pub DynServerModuleInit(Arc<IServerModuleInit>)
270);
271
272impl AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static> for DynServerModuleInit {
273 fn as_ref(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
274 self.inner.as_common()
275 }
276}
277
278pub type ServerModuleInitRegistry = ModuleInitRegistry<DynServerModuleInit>;
279
280pub trait ServerModuleInitRegistryExt {
281 fn to_common(&self) -> CommonModuleInitRegistry;
282}
283
284impl ServerModuleInitRegistryExt for ServerModuleInitRegistry {
285 fn to_common(&self) -> CommonModuleInitRegistry {
286 self.iter().map(|(_k, v)| v.to_dyn_common()).collect()
287 }
288}