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