1#![deny(clippy::pedantic)]
2#![allow(clippy::module_name_repetitions)]
3#![allow(clippy::must_use_candidate)]
4
5use std::collections::BTreeMap;
6
7use anyhow::bail;
8use async_trait::async_trait;
9use fedimint_core::config::{
10 ConfigGenModuleParams, ServerModuleConfig, ServerModuleConsensusConfig,
11 TypedServerModuleConfig, TypedServerModuleConsensusConfig,
12};
13use fedimint_core::core::ModuleInstanceId;
14use fedimint_core::db::{CoreMigrationFn, DatabaseTransaction, DatabaseVersion};
15use fedimint_core::module::audit::Audit;
16use fedimint_core::module::{
17 ApiEndpoint, CORE_CONSENSUS_VERSION, CoreConsensusVersion, InputMeta, ModuleConsensusVersion,
18 ModuleInit, PeerHandle, SupportedModuleApiVersions, TransactionItemAmount,
19};
20use fedimint_core::{InPoint, OutPoint, PeerId, push_db_pair_items};
21use fedimint_empty_common::config::{
22 EmptyClientConfig, EmptyConfig, EmptyConfigConsensus, EmptyConfigLocal, EmptyConfigPrivate,
23 EmptyGenParams,
24};
25use fedimint_empty_common::{
26 EmptyCommonInit, EmptyConsensusItem, EmptyInput, EmptyInputError, EmptyModuleTypes,
27 EmptyOutput, EmptyOutputError, EmptyOutputOutcome, MODULE_CONSENSUS_VERSION,
28};
29use fedimint_server_core::{ServerModule, ServerModuleInit, ServerModuleInitArgs};
30use futures::StreamExt;
31use strum::IntoEnumIterator;
32
33use crate::db::{DbKeyPrefix, EmptyExampleKeyPrefix};
34
35pub mod db;
36
37#[derive(Debug, Clone)]
39pub struct EmptyInit;
40
41impl ModuleInit for EmptyInit {
43 type Common = EmptyCommonInit;
44
45 async fn dump_database(
47 &self,
48 dbtx: &mut DatabaseTransaction<'_>,
49 prefix_names: Vec<String>,
50 ) -> Box<dyn Iterator<Item = (String, Box<dyn erased_serde::Serialize + Send>)> + '_> {
51 let mut items: BTreeMap<String, Box<dyn erased_serde::Serialize + Send>> = BTreeMap::new();
53 let filtered_prefixes = DbKeyPrefix::iter().filter(|f| {
54 prefix_names.is_empty() || prefix_names.contains(&f.to_string().to_lowercase())
55 });
56
57 for table in filtered_prefixes {
58 match table {
59 DbKeyPrefix::Example => {
60 push_db_pair_items!(
61 dbtx,
62 EmptyExampleKeyPrefix,
63 EmptyExampleKey,
64 Vec<u8>,
65 items,
66 "Empty Example"
67 );
68 }
69 }
70 }
71
72 Box::new(items.into_iter())
73 }
74}
75
76#[async_trait]
78impl ServerModuleInit for EmptyInit {
79 type Module = Empty;
80 type Params = EmptyGenParams;
81
82 fn versions(&self, _core: CoreConsensusVersion) -> &[ModuleConsensusVersion] {
84 &[MODULE_CONSENSUS_VERSION]
85 }
86
87 fn supported_api_versions(&self) -> SupportedModuleApiVersions {
88 SupportedModuleApiVersions::from_raw(
89 (CORE_CONSENSUS_VERSION.major, CORE_CONSENSUS_VERSION.minor),
90 (
91 MODULE_CONSENSUS_VERSION.major,
92 MODULE_CONSENSUS_VERSION.minor,
93 ),
94 &[(0, 0)],
95 )
96 }
97
98 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module> {
100 Ok(Empty::new(args.cfg().to_typed()?))
101 }
102
103 fn trusted_dealer_gen(
105 &self,
106 peers: &[PeerId],
107 params: &ConfigGenModuleParams,
108 ) -> BTreeMap<PeerId, ServerModuleConfig> {
109 let _params = self.parse_params(params).unwrap();
110 peers
112 .iter()
113 .map(|&peer| {
114 let config = EmptyConfig {
115 local: EmptyConfigLocal {},
116 private: EmptyConfigPrivate,
117 consensus: EmptyConfigConsensus {},
118 };
119 (peer, config.to_erased())
120 })
121 .collect()
122 }
123
124 async fn distributed_gen(
126 &self,
127 _peers: &PeerHandle,
128 params: &ConfigGenModuleParams,
129 ) -> anyhow::Result<ServerModuleConfig> {
130 let _params = self.parse_params(params).unwrap();
131
132 Ok(EmptyConfig {
133 local: EmptyConfigLocal {},
134 private: EmptyConfigPrivate,
135 consensus: EmptyConfigConsensus {},
136 }
137 .to_erased())
138 }
139
140 fn get_client_config(
142 &self,
143 config: &ServerModuleConsensusConfig,
144 ) -> anyhow::Result<EmptyClientConfig> {
145 let _config = EmptyConfigConsensus::from_erased(config)?;
146 Ok(EmptyClientConfig {})
147 }
148
149 fn validate_config(
150 &self,
151 _identity: &PeerId,
152 _config: ServerModuleConfig,
153 ) -> anyhow::Result<()> {
154 Ok(())
155 }
156
157 fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, CoreMigrationFn> {
159 BTreeMap::new()
160 }
161}
162
163#[derive(Debug)]
165pub struct Empty {
166 pub cfg: EmptyConfig,
167}
168
169#[async_trait]
171impl ServerModule for Empty {
172 type Common = EmptyModuleTypes;
174 type Init = EmptyInit;
175
176 async fn consensus_proposal(
177 &self,
178 _dbtx: &mut DatabaseTransaction<'_>,
179 ) -> Vec<EmptyConsensusItem> {
180 Vec::new()
181 }
182
183 async fn process_consensus_item<'a, 'b>(
184 &'a self,
185 _dbtx: &mut DatabaseTransaction<'b>,
186 _consensus_item: EmptyConsensusItem,
187 _peer_id: PeerId,
188 ) -> anyhow::Result<()> {
189 bail!("The empty module does not use consensus items");
195 }
196
197 async fn process_input<'a, 'b, 'c>(
198 &'a self,
199 _dbtx: &mut DatabaseTransaction<'c>,
200 _input: &'b EmptyInput,
201 _in_point: InPoint,
202 ) -> Result<InputMeta, EmptyInputError> {
203 Err(EmptyInputError::NotSupported)
204 }
205
206 async fn process_output<'a, 'b>(
207 &'a self,
208 _dbtx: &mut DatabaseTransaction<'b>,
209 _output: &'a EmptyOutput,
210 _out_point: OutPoint,
211 ) -> Result<TransactionItemAmount, EmptyOutputError> {
212 Err(EmptyOutputError::NotSupported)
213 }
214
215 async fn output_status(
216 &self,
217 _dbtx: &mut DatabaseTransaction<'_>,
218 _out_point: OutPoint,
219 ) -> Option<EmptyOutputOutcome> {
220 None
221 }
222
223 async fn audit(
224 &self,
225 _dbtx: &mut DatabaseTransaction<'_>,
226 _audit: &mut Audit,
227 _module_instance_id: ModuleInstanceId,
228 ) {
229 }
230
231 fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
232 Vec::new()
233 }
234}
235
236impl Empty {
237 pub fn new(cfg: EmptyConfig) -> Empty {
239 Empty { cfg }
240 }
241}