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