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 ServerModuleConfig, ServerModuleConsensusConfig, TypedServerModuleConfig,
11 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, TransactionItemAmounts,
19};
20use fedimint_core::{InPoint, OutPoint, PeerId, push_db_pair_items};
21use fedimint_empty_common::config::{
22 EmptyClientConfig, EmptyConfig, EmptyConfigConsensus, EmptyConfigPrivate,
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::{
31 ConfigGenModuleArgs, ServerModule, ServerModuleInit, ServerModuleInitArgs,
32};
33use futures::StreamExt;
34use strum::IntoEnumIterator;
35
36use crate::db::{DbKeyPrefix, EmptyExampleKeyPrefix};
37
38pub mod db;
39
40#[derive(Debug, Clone)]
42pub struct EmptyInit;
43
44impl ModuleInit for EmptyInit {
46 type Common = EmptyCommonInit;
47
48 async fn dump_database(
50 &self,
51 dbtx: &mut DatabaseTransaction<'_>,
52 prefix_names: Vec<String>,
53 ) -> Box<dyn Iterator<Item = (String, Box<dyn erased_serde::Serialize + Send>)> + '_> {
54 let mut items: BTreeMap<String, Box<dyn erased_serde::Serialize + Send>> = BTreeMap::new();
56 let filtered_prefixes = DbKeyPrefix::iter().filter(|f| {
57 prefix_names.is_empty() || prefix_names.contains(&f.to_string().to_lowercase())
58 });
59
60 for table in filtered_prefixes {
61 match table {
62 DbKeyPrefix::Example => {
63 push_db_pair_items!(
64 dbtx,
65 EmptyExampleKeyPrefix,
66 EmptyExampleKey,
67 Vec<u8>,
68 items,
69 "Empty Example"
70 );
71 }
72 }
73 }
74
75 Box::new(items.into_iter())
76 }
77}
78
79#[async_trait]
81impl ServerModuleInit for EmptyInit {
82 type Module = Empty;
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 _args: &ConfigGenModuleArgs,
110 ) -> BTreeMap<PeerId, ServerModuleConfig> {
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 _args: &ConfigGenModuleArgs,
129 ) -> anyhow::Result<ServerModuleConfig> {
130 Ok(EmptyConfig {
131 private: EmptyConfigPrivate,
132 consensus: EmptyConfigConsensus {},
133 }
134 .to_erased())
135 }
136
137 fn get_client_config(
139 &self,
140 config: &ServerModuleConsensusConfig,
141 ) -> anyhow::Result<EmptyClientConfig> {
142 let _config = EmptyConfigConsensus::from_erased(config)?;
143 Ok(EmptyClientConfig {})
144 }
145
146 fn validate_config(
147 &self,
148 _identity: &PeerId,
149 _config: ServerModuleConfig,
150 ) -> anyhow::Result<()> {
151 Ok(())
152 }
153
154 fn get_database_migrations(
156 &self,
157 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Empty>> {
158 BTreeMap::new()
159 }
160}
161
162#[derive(Debug)]
164pub struct Empty {
165 pub cfg: EmptyConfig,
166}
167
168#[async_trait]
170impl ServerModule for Empty {
171 type Common = EmptyModuleTypes;
173 type Init = EmptyInit;
174
175 async fn consensus_proposal(
176 &self,
177 _dbtx: &mut DatabaseTransaction<'_>,
178 ) -> Vec<EmptyConsensusItem> {
179 Vec::new()
180 }
181
182 async fn process_consensus_item<'a, 'b>(
183 &'a self,
184 _dbtx: &mut DatabaseTransaction<'b>,
185 _consensus_item: EmptyConsensusItem,
186 _peer_id: PeerId,
187 ) -> anyhow::Result<()> {
188 bail!("The empty module does not use consensus items");
194 }
195
196 async fn process_input<'a, 'b, 'c>(
197 &'a self,
198 _dbtx: &mut DatabaseTransaction<'c>,
199 _input: &'b EmptyInput,
200 _in_point: InPoint,
201 ) -> Result<InputMeta, EmptyInputError> {
202 Err(EmptyInputError::NotSupported)
203 }
204
205 async fn process_output<'a, 'b>(
206 &'a self,
207 _dbtx: &mut DatabaseTransaction<'b>,
208 _output: &'a EmptyOutput,
209 _out_point: OutPoint,
210 ) -> Result<TransactionItemAmounts, EmptyOutputError> {
211 Err(EmptyOutputError::NotSupported)
212 }
213
214 async fn output_status(
215 &self,
216 _dbtx: &mut DatabaseTransaction<'_>,
217 _out_point: OutPoint,
218 ) -> Option<EmptyOutputOutcome> {
219 None
220 }
221
222 async fn audit(
223 &self,
224 _dbtx: &mut DatabaseTransaction<'_>,
225 _audit: &mut Audit,
226 _module_instance_id: ModuleInstanceId,
227 ) {
228 }
229
230 fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
231 Vec::new()
232 }
233}
234
235impl Empty {
236 pub fn new(cfg: EmptyConfig) -> Empty {
238 Empty { cfg }
239 }
240}