1#![allow(clippy::pedantic)]
3
4use std::collections::{BTreeMap, BTreeSet};
5use std::marker::PhantomData;
6use std::sync::Arc;
7use std::{any, marker};
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::{Database, DatabaseVersion};
16use fedimint_core::module::{
17 CommonModuleInit, CoreConsensusVersion, IDynCommonModuleInit, ModuleConsensusVersion,
18 ModuleInit, SupportedModuleApiVersions,
19};
20use fedimint_core::task::TaskGroup;
21use fedimint_core::{NumPeers, PeerId, apply, async_trait_maybe_send, dyn_newtype_define};
22
23use crate::bitcoin_rpc::ServerBitcoinRpcMonitor;
24use crate::config::PeerHandleOps;
25use crate::migration::{
26 DynServerDbMigrationFn, ServerDbMigrationFnContext, ServerModuleDbMigrationContext,
27 ServerModuleDbMigrationFn,
28};
29use crate::{DynServerModule, ServerModule};
30
31#[apply(async_trait_maybe_send!)]
41pub trait IServerModuleInit: IDynCommonModuleInit {
42 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static);
43
44 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
45
46 #[allow(clippy::too_many_arguments)]
48 async fn init(
49 &self,
50 peer_num: NumPeers,
51 cfg: ServerModuleConfig,
52 db: Database,
53 task_group: &TaskGroup,
54 our_peer_id: PeerId,
55 module_api: DynModuleApi,
56 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
57 ) -> anyhow::Result<DynServerModule>;
58
59 fn validate_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<()>;
60
61 fn trusted_dealer_gen(
62 &self,
63 peers: &[PeerId],
64 params: &ConfigGenModuleParams,
65 ) -> BTreeMap<PeerId, ServerModuleConfig>;
66
67 async fn distributed_gen(
68 &self,
69 peers: &(dyn PeerHandleOps + Send + Sync),
70 params: &ConfigGenModuleParams,
71 ) -> anyhow::Result<ServerModuleConfig>;
72
73 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
74
75 fn get_client_config(
76 &self,
77 module_instance_id: ModuleInstanceId,
78 config: &ServerModuleConsensusConfig,
79 ) -> anyhow::Result<ClientModuleConfig>;
80
81 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, DynServerDbMigrationFn>;
85
86 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>>;
88}
89
90pub trait ServerModuleShared: any::Any + Send + Sync {
93 fn new(task_group: TaskGroup) -> Self;
94}
95
96pub struct ServerModuleInitArgs<S>
97where
98 S: ServerModuleInit,
99{
100 cfg: ServerModuleConfig,
101 db: Database,
102 task_group: TaskGroup,
103 our_peer_id: PeerId,
104 num_peers: NumPeers,
105 module_api: DynModuleApi,
106 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
107 _marker: marker::PhantomData<S>,
110}
111
112impl<S> ServerModuleInitArgs<S>
113where
114 S: ServerModuleInit,
115{
116 pub fn cfg(&self) -> &ServerModuleConfig {
117 &self.cfg
118 }
119
120 pub fn db(&self) -> &Database {
121 &self.db
122 }
123
124 pub fn num_peers(&self) -> NumPeers {
125 self.num_peers
126 }
127
128 pub fn task_group(&self) -> &TaskGroup {
129 &self.task_group
130 }
131
132 pub fn our_peer_id(&self) -> PeerId {
133 self.our_peer_id
134 }
135
136 pub fn module_api(&self) -> &DynModuleApi {
137 &self.module_api
138 }
139
140 pub fn server_bitcoin_rpc_monitor(&self) -> ServerBitcoinRpcMonitor {
141 self.server_bitcoin_rpc_monitor.clone()
142 }
143}
144#[apply(async_trait_maybe_send!)]
151pub trait ServerModuleInit: ModuleInit + Sized {
152 type Module: ServerModule + Send + Sync;
153 type Params: ModuleInitParams;
154
155 fn versions(&self, core: CoreConsensusVersion) -> &[ModuleConsensusVersion];
168
169 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
170
171 fn kind() -> ModuleKind {
172 <Self as ModuleInit>::Common::KIND
173 }
174
175 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module>;
177
178 fn parse_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<Self::Params> {
179 params.to_typed::<Self::Params>()
180 }
181
182 fn trusted_dealer_gen(
183 &self,
184 peers: &[PeerId],
185 params: &ConfigGenModuleParams,
186 ) -> BTreeMap<PeerId, ServerModuleConfig>;
187
188 async fn distributed_gen(
189 &self,
190 peers: &(dyn PeerHandleOps + Send + Sync),
191 params: &ConfigGenModuleParams,
192 ) -> anyhow::Result<ServerModuleConfig>;
193
194 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
195
196 fn get_client_config(
198 &self,
199 config: &ServerModuleConsensusConfig,
200 ) -> anyhow::Result<<<Self as ModuleInit>::Common as CommonModuleInit>::ClientConfig>;
201
202 fn get_database_migrations(
206 &self,
207 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Self::Module>> {
208 BTreeMap::new()
209 }
210
211 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>> {
221 None
222 }
223}
224
225#[apply(async_trait_maybe_send!)]
226impl<T> IServerModuleInit for T
227where
228 T: ServerModuleInit + 'static + Sync,
229{
230 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
231 self
232 }
233
234 fn supported_api_versions(&self) -> SupportedModuleApiVersions {
235 <Self as ServerModuleInit>::supported_api_versions(self)
236 }
237
238 async fn init(
239 &self,
240 num_peers: NumPeers,
241 cfg: ServerModuleConfig,
242 db: Database,
243 task_group: &TaskGroup,
244 our_peer_id: PeerId,
245 module_api: DynModuleApi,
246 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
247 ) -> anyhow::Result<DynServerModule> {
248 let module = <Self as ServerModuleInit>::init(
249 self,
250 &ServerModuleInitArgs {
251 num_peers,
252 cfg,
253 db,
254 task_group: task_group.clone(),
255 our_peer_id,
256 _marker: PhantomData,
257 module_api,
258 server_bitcoin_rpc_monitor,
259 },
260 )
261 .await?;
262
263 Ok(DynServerModule::from(module))
264 }
265
266 fn validate_params(&self, params: &ConfigGenModuleParams) -> anyhow::Result<()> {
267 <Self as ServerModuleInit>::parse_params(self, params)?;
268 Ok(())
269 }
270
271 fn trusted_dealer_gen(
272 &self,
273 peers: &[PeerId],
274 params: &ConfigGenModuleParams,
275 ) -> BTreeMap<PeerId, ServerModuleConfig> {
276 <Self as ServerModuleInit>::trusted_dealer_gen(self, peers, params)
277 }
278
279 async fn distributed_gen(
280 &self,
281 peers: &(dyn PeerHandleOps + Send + Sync),
282 params: &ConfigGenModuleParams,
283 ) -> anyhow::Result<ServerModuleConfig> {
284 <Self as ServerModuleInit>::distributed_gen(self, peers, params).await
285 }
286
287 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()> {
288 <Self as ServerModuleInit>::validate_config(self, identity, config)
289 }
290
291 fn get_client_config(
292 &self,
293 module_instance_id: ModuleInstanceId,
294 config: &ServerModuleConsensusConfig,
295 ) -> anyhow::Result<ClientModuleConfig> {
296 ClientModuleConfig::from_typed(
297 module_instance_id,
298 <Self as ServerModuleInit>::kind(),
299 config.version,
300 <Self as ServerModuleInit>::get_client_config(self, config)?,
301 )
302 }
303 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, DynServerDbMigrationFn> {
304 <Self as ServerModuleInit>::get_database_migrations(self)
305 .into_iter()
306 .map(|(k, f)| {
307 (k, {
308 let closure: DynServerDbMigrationFn =
309 Box::new(move |ctx: ServerDbMigrationFnContext<'_>| {
310 let map = ctx.map(ServerModuleDbMigrationContext::new);
311 Box::pin(f(map))
312 });
313 closure
314 })
315 })
316 .collect()
317 }
318
319 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>> {
320 <Self as ServerModuleInit>::used_db_prefixes(self)
321 }
322}
323
324dyn_newtype_define!(
325 #[derive(Clone)]
326 pub DynServerModuleInit(Arc<IServerModuleInit>)
327);
328
329impl AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static> for DynServerModuleInit {
330 fn as_ref(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
331 self.inner.as_common()
332 }
333}
334
335pub type ServerModuleInitRegistry = ModuleInitRegistry<DynServerModuleInit>;
336
337pub trait ServerModuleInitRegistryExt {
338 fn to_common(&self) -> CommonModuleInitRegistry;
339}
340
341impl ServerModuleInitRegistryExt for ServerModuleInitRegistry {
342 fn to_common(&self) -> CommonModuleInitRegistry {
343 self.iter().map(|(_k, v)| v.to_dyn_common()).collect()
344 }
345}