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 _disable_base_fees: bool,
110 ) -> BTreeMap<PeerId, ServerModuleConfig> {
111 let _params = self.parse_params(params).unwrap();
112 peers
114 .iter()
115 .map(|&peer| {
116 let config = EmptyConfig {
117 private: EmptyConfigPrivate,
118 consensus: EmptyConfigConsensus {},
119 };
120 (peer, config.to_erased())
121 })
122 .collect()
123 }
124
125 async fn distributed_gen(
127 &self,
128 _peers: &(dyn PeerHandleOps + Send + Sync),
129 params: &ConfigGenModuleParams,
130 _disable_base_fees: bool,
131 ) -> anyhow::Result<ServerModuleConfig> {
132 let _params = self.parse_params(params).unwrap();
133
134 Ok(EmptyConfig {
135 private: EmptyConfigPrivate,
136 consensus: EmptyConfigConsensus {},
137 }
138 .to_erased())
139 }
140
141 fn get_client_config(
143 &self,
144 config: &ServerModuleConsensusConfig,
145 ) -> anyhow::Result<EmptyClientConfig> {
146 let _config = EmptyConfigConsensus::from_erased(config)?;
147 Ok(EmptyClientConfig {})
148 }
149
150 fn validate_config(
151 &self,
152 _identity: &PeerId,
153 _config: ServerModuleConfig,
154 ) -> anyhow::Result<()> {
155 Ok(())
156 }
157
158 fn get_database_migrations(
160 &self,
161 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Empty>> {
162 BTreeMap::new()
163 }
164}
165
166#[derive(Debug)]
168pub struct Empty {
169 pub cfg: EmptyConfig,
170}
171
172#[async_trait]
174impl ServerModule for Empty {
175 type Common = EmptyModuleTypes;
177 type Init = EmptyInit;
178
179 async fn consensus_proposal(
180 &self,
181 _dbtx: &mut DatabaseTransaction<'_>,
182 ) -> Vec<EmptyConsensusItem> {
183 Vec::new()
184 }
185
186 async fn process_consensus_item<'a, 'b>(
187 &'a self,
188 _dbtx: &mut DatabaseTransaction<'b>,
189 _consensus_item: EmptyConsensusItem,
190 _peer_id: PeerId,
191 ) -> anyhow::Result<()> {
192 bail!("The empty module does not use consensus items");
198 }
199
200 async fn process_input<'a, 'b, 'c>(
201 &'a self,
202 _dbtx: &mut DatabaseTransaction<'c>,
203 _input: &'b EmptyInput,
204 _in_point: InPoint,
205 ) -> Result<InputMeta, EmptyInputError> {
206 Err(EmptyInputError::NotSupported)
207 }
208
209 async fn process_output<'a, 'b>(
210 &'a self,
211 _dbtx: &mut DatabaseTransaction<'b>,
212 _output: &'a EmptyOutput,
213 _out_point: OutPoint,
214 ) -> Result<TransactionItemAmount, EmptyOutputError> {
215 Err(EmptyOutputError::NotSupported)
216 }
217
218 async fn output_status(
219 &self,
220 _dbtx: &mut DatabaseTransaction<'_>,
221 _out_point: OutPoint,
222 ) -> Option<EmptyOutputOutcome> {
223 None
224 }
225
226 async fn audit(
227 &self,
228 _dbtx: &mut DatabaseTransaction<'_>,
229 _audit: &mut Audit,
230 _module_instance_id: ModuleInstanceId,
231 ) {
232 }
233
234 fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
235 Vec::new()
236 }
237}
238
239impl Empty {
240 pub fn new(cfg: EmptyConfig) -> Empty {
242 Empty { cfg }
243 }
244}