1#![allow(clippy::pedantic)]
3
4use std::collections::{BTreeMap, BTreeSet};
5use std::marker::PhantomData;
6use std::sync::Arc;
7use std::{any, marker};
8
9use bitcoin::Network;
10use fedimint_api_client::api::DynModuleApi;
11use fedimint_core::config::{
12 ClientModuleConfig, CommonModuleInitRegistry, ModuleInitRegistry, ServerModuleConfig,
13 ServerModuleConsensusConfig,
14};
15use fedimint_core::core::{ModuleInstanceId, ModuleKind};
16use fedimint_core::db::{Database, DatabaseVersion};
17use fedimint_core::module::{
18 CommonModuleInit, CoreConsensusVersion, IDynCommonModuleInit, ModuleConsensusVersion,
19 ModuleInit, SupportedModuleApiVersions,
20};
21use fedimint_core::task::TaskGroup;
22use fedimint_core::{NumPeers, PeerId, apply, async_trait_maybe_send, dyn_newtype_define};
23
24use crate::bitcoin_rpc::ServerBitcoinRpcMonitor;
25use crate::config::PeerHandleOps;
26use crate::migration::{
27 DynServerDbMigrationFn, ServerDbMigrationFnContext, ServerModuleDbMigrationContext,
28 ServerModuleDbMigrationFn,
29};
30use crate::{DynServerModule, ServerModule};
31
32#[derive(Debug, Clone, Copy)]
37pub struct ConfigGenModuleArgs {
38 pub network: Network,
40 pub disable_base_fees: bool,
42}
43
44#[apply(async_trait_maybe_send!)]
54pub trait IServerModuleInit: IDynCommonModuleInit {
55 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static);
56
57 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
58
59 #[allow(clippy::too_many_arguments)]
61 async fn init(
62 &self,
63 peer_num: NumPeers,
64 cfg: ServerModuleConfig,
65 db: Database,
66 task_group: &TaskGroup,
67 our_peer_id: PeerId,
68 module_api: DynModuleApi,
69 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
70 ) -> anyhow::Result<DynServerModule>;
71
72 fn trusted_dealer_gen(
73 &self,
74 peers: &[PeerId],
75 args: &ConfigGenModuleArgs,
76 ) -> BTreeMap<PeerId, ServerModuleConfig>;
77
78 async fn distributed_gen(
79 &self,
80 peers: &(dyn PeerHandleOps + Send + Sync),
81 args: &ConfigGenModuleArgs,
82 ) -> anyhow::Result<ServerModuleConfig>;
83
84 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
85
86 fn get_client_config(
87 &self,
88 module_instance_id: ModuleInstanceId,
89 config: &ServerModuleConsensusConfig,
90 ) -> anyhow::Result<ClientModuleConfig>;
91
92 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, DynServerDbMigrationFn>;
96
97 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>>;
99
100 fn is_enabled_by_default(&self) -> bool;
102}
103
104pub trait ServerModuleShared: any::Any + Send + Sync {
107 fn new(task_group: TaskGroup) -> Self;
108}
109
110pub struct ServerModuleInitArgs<S>
111where
112 S: ServerModuleInit,
113{
114 cfg: ServerModuleConfig,
115 db: Database,
116 task_group: TaskGroup,
117 our_peer_id: PeerId,
118 num_peers: NumPeers,
119 module_api: DynModuleApi,
120 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
121 _marker: marker::PhantomData<S>,
124}
125
126impl<S> ServerModuleInitArgs<S>
127where
128 S: ServerModuleInit,
129{
130 pub fn cfg(&self) -> &ServerModuleConfig {
131 &self.cfg
132 }
133
134 pub fn db(&self) -> &Database {
135 &self.db
136 }
137
138 pub fn num_peers(&self) -> NumPeers {
139 self.num_peers
140 }
141
142 pub fn task_group(&self) -> &TaskGroup {
143 &self.task_group
144 }
145
146 pub fn our_peer_id(&self) -> PeerId {
147 self.our_peer_id
148 }
149
150 pub fn module_api(&self) -> &DynModuleApi {
151 &self.module_api
152 }
153
154 pub fn server_bitcoin_rpc_monitor(&self) -> ServerBitcoinRpcMonitor {
155 self.server_bitcoin_rpc_monitor.clone()
156 }
157}
158#[apply(async_trait_maybe_send!)]
165pub trait ServerModuleInit: ModuleInit + Sized {
166 type Module: ServerModule + Send + Sync;
167
168 fn versions(&self, core: CoreConsensusVersion) -> &[ModuleConsensusVersion];
181
182 fn supported_api_versions(&self) -> SupportedModuleApiVersions;
183
184 fn kind() -> ModuleKind {
185 <Self as ModuleInit>::Common::KIND
186 }
187
188 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module>;
190
191 fn trusted_dealer_gen(
192 &self,
193 peers: &[PeerId],
194 args: &ConfigGenModuleArgs,
195 ) -> BTreeMap<PeerId, ServerModuleConfig>;
196
197 async fn distributed_gen(
198 &self,
199 peers: &(dyn PeerHandleOps + Send + Sync),
200 args: &ConfigGenModuleArgs,
201 ) -> anyhow::Result<ServerModuleConfig>;
202
203 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()>;
204
205 fn get_client_config(
207 &self,
208 config: &ServerModuleConsensusConfig,
209 ) -> anyhow::Result<<<Self as ModuleInit>::Common as CommonModuleInit>::ClientConfig>;
210
211 fn get_database_migrations(
215 &self,
216 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Self::Module>> {
217 BTreeMap::new()
218 }
219
220 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>> {
230 None
231 }
232
233 fn is_enabled_by_default(&self) -> bool {
236 true
237 }
238}
239
240#[apply(async_trait_maybe_send!)]
241impl<T> IServerModuleInit for T
242where
243 T: ServerModuleInit + 'static + Sync,
244{
245 fn as_common(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
246 self
247 }
248
249 fn supported_api_versions(&self) -> SupportedModuleApiVersions {
250 <Self as ServerModuleInit>::supported_api_versions(self)
251 }
252
253 async fn init(
254 &self,
255 num_peers: NumPeers,
256 cfg: ServerModuleConfig,
257 db: Database,
258 task_group: &TaskGroup,
259 our_peer_id: PeerId,
260 module_api: DynModuleApi,
261 server_bitcoin_rpc_monitor: ServerBitcoinRpcMonitor,
262 ) -> anyhow::Result<DynServerModule> {
263 let module = <Self as ServerModuleInit>::init(
264 self,
265 &ServerModuleInitArgs {
266 num_peers,
267 cfg,
268 db,
269 task_group: task_group.clone(),
270 our_peer_id,
271 _marker: PhantomData,
272 module_api,
273 server_bitcoin_rpc_monitor,
274 },
275 )
276 .await?;
277
278 Ok(DynServerModule::from(module))
279 }
280
281 fn trusted_dealer_gen(
282 &self,
283 peers: &[PeerId],
284 args: &ConfigGenModuleArgs,
285 ) -> BTreeMap<PeerId, ServerModuleConfig> {
286 <Self as ServerModuleInit>::trusted_dealer_gen(self, peers, args)
287 }
288
289 async fn distributed_gen(
290 &self,
291 peers: &(dyn PeerHandleOps + Send + Sync),
292 args: &ConfigGenModuleArgs,
293 ) -> anyhow::Result<ServerModuleConfig> {
294 <Self as ServerModuleInit>::distributed_gen(self, peers, args).await
295 }
296
297 fn validate_config(&self, identity: &PeerId, config: ServerModuleConfig) -> anyhow::Result<()> {
298 <Self as ServerModuleInit>::validate_config(self, identity, config)
299 }
300
301 fn get_client_config(
302 &self,
303 module_instance_id: ModuleInstanceId,
304 config: &ServerModuleConsensusConfig,
305 ) -> anyhow::Result<ClientModuleConfig> {
306 ClientModuleConfig::from_typed(
307 module_instance_id,
308 <Self as ServerModuleInit>::kind(),
309 config.version,
310 <Self as ServerModuleInit>::get_client_config(self, config)?,
311 )
312 }
313 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, DynServerDbMigrationFn> {
314 <Self as ServerModuleInit>::get_database_migrations(self)
315 .into_iter()
316 .map(|(k, f)| {
317 (k, {
318 let closure: DynServerDbMigrationFn =
319 Box::new(move |ctx: ServerDbMigrationFnContext<'_>| {
320 let map = ctx.map(ServerModuleDbMigrationContext::new);
321 Box::pin(f(map))
322 });
323 closure
324 })
325 })
326 .collect()
327 }
328
329 fn used_db_prefixes(&self) -> Option<BTreeSet<u8>> {
330 <Self as ServerModuleInit>::used_db_prefixes(self)
331 }
332
333 fn is_enabled_by_default(&self) -> bool {
334 <Self as ServerModuleInit>::is_enabled_by_default(self)
335 }
336}
337
338dyn_newtype_define!(
339 #[derive(Clone)]
340 pub DynServerModuleInit(Arc<IServerModuleInit>)
341);
342
343impl AsRef<dyn IDynCommonModuleInit + Send + Sync + 'static> for DynServerModuleInit {
344 fn as_ref(&self) -> &(dyn IDynCommonModuleInit + Send + Sync + 'static) {
345 self.inner.as_common()
346 }
347}
348
349pub type ServerModuleInitRegistry = ModuleInitRegistry<DynServerModuleInit>;
350
351pub trait ServerModuleInitRegistryExt {
352 fn to_common(&self) -> CommonModuleInitRegistry;
353 fn default_modules(&self) -> BTreeSet<ModuleKind>;
354}
355
356impl ServerModuleInitRegistryExt for ServerModuleInitRegistry {
357 fn to_common(&self) -> CommonModuleInitRegistry {
358 self.iter().map(|(_k, v)| v.to_dyn_common()).collect()
359 }
360
361 fn default_modules(&self) -> BTreeSet<ModuleKind> {
362 self.iter()
363 .filter(|(_kind, init)| init.is_enabled_by_default())
364 .map(|(kind, _init)| kind.clone())
365 .collect()
366 }
367}