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, CoreConsensusVersion, InputMeta, ModuleConsensusVersion, ModuleInit,
18 TransactionItemAmounts,
19};
20use fedimint_core::{InPoint, OutPoint, PeerId, push_db_pair_items};
21pub use fedimint_empty_common as common;
22use fedimint_empty_common::config::{
23 EmptyClientConfig, EmptyConfig, EmptyConfigConsensus, EmptyConfigPrivate,
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::{
32 ConfigGenModuleArgs, ServerModule, ServerModuleInit, ServerModuleInitArgs,
33};
34use futures::StreamExt;
35use strum::IntoEnumIterator;
36
37use crate::db::{DbKeyPrefix, EmptyExampleKeyPrefix};
38
39pub mod db;
40
41#[derive(Debug, Clone)]
43pub struct EmptyInit;
44
45impl ModuleInit for EmptyInit {
47 type Common = EmptyCommonInit;
48
49 async fn dump_database(
51 &self,
52 dbtx: &mut DatabaseTransaction<'_>,
53 prefix_names: Vec<String>,
54 ) -> Box<dyn Iterator<Item = (String, Box<dyn erased_serde::Serialize + Send>)> + '_> {
55 let mut items: BTreeMap<String, Box<dyn erased_serde::Serialize + Send>> = BTreeMap::new();
57 let filtered_prefixes = DbKeyPrefix::iter().filter(|f| {
58 prefix_names.is_empty() || prefix_names.contains(&f.to_string().to_lowercase())
59 });
60
61 for table in filtered_prefixes {
62 match table {
63 DbKeyPrefix::Example => {
64 push_db_pair_items!(
65 dbtx,
66 EmptyExampleKeyPrefix,
67 EmptyExampleKey,
68 Vec<u8>,
69 items,
70 "Empty Example"
71 );
72 }
73 }
74 }
75
76 Box::new(items.into_iter())
77 }
78}
79
80#[async_trait]
82impl ServerModuleInit for EmptyInit {
83 type Module = Empty;
84
85 fn versions(&self, _core: CoreConsensusVersion) -> &[ModuleConsensusVersion] {
87 &[MODULE_CONSENSUS_VERSION]
88 }
89
90 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module> {
92 Ok(Empty::new(args.cfg().to_typed()?))
93 }
94
95 fn trusted_dealer_gen(
97 &self,
98 peers: &[PeerId],
99 _args: &ConfigGenModuleArgs,
100 ) -> BTreeMap<PeerId, ServerModuleConfig> {
101 peers
103 .iter()
104 .map(|&peer| {
105 let config = EmptyConfig {
106 private: EmptyConfigPrivate,
107 consensus: EmptyConfigConsensus {},
108 };
109 (peer, config.to_erased())
110 })
111 .collect()
112 }
113
114 async fn distributed_gen(
116 &self,
117 _peers: &(dyn PeerHandleOps + Send + Sync),
118 _args: &ConfigGenModuleArgs,
119 ) -> anyhow::Result<ServerModuleConfig> {
120 Ok(EmptyConfig {
121 private: EmptyConfigPrivate,
122 consensus: EmptyConfigConsensus {},
123 }
124 .to_erased())
125 }
126
127 fn get_client_config(
129 &self,
130 config: &ServerModuleConsensusConfig,
131 ) -> anyhow::Result<EmptyClientConfig> {
132 let _config = EmptyConfigConsensus::from_erased(config)?;
133 Ok(EmptyClientConfig {})
134 }
135
136 fn validate_config(
137 &self,
138 _identity: &PeerId,
139 _config: ServerModuleConfig,
140 ) -> anyhow::Result<()> {
141 Ok(())
142 }
143
144 fn get_database_migrations(
146 &self,
147 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Empty>> {
148 BTreeMap::new()
149 }
150}
151
152#[derive(Debug)]
154pub struct Empty {
155 pub cfg: EmptyConfig,
156}
157
158#[async_trait]
160impl ServerModule for Empty {
161 type Common = EmptyModuleTypes;
163 type Init = EmptyInit;
164
165 async fn consensus_proposal(
166 &self,
167 _dbtx: &mut DatabaseTransaction<'_>,
168 ) -> Vec<EmptyConsensusItem> {
169 Vec::new()
170 }
171
172 async fn process_consensus_item<'a, 'b>(
173 &'a self,
174 _dbtx: &mut DatabaseTransaction<'b>,
175 _consensus_item: EmptyConsensusItem,
176 _peer_id: PeerId,
177 ) -> anyhow::Result<()> {
178 bail!("The empty module does not use consensus items");
184 }
185
186 async fn process_input<'a, 'b, 'c>(
187 &'a self,
188 _dbtx: &mut DatabaseTransaction<'c>,
189 _input: &'b EmptyInput,
190 _in_point: InPoint,
191 ) -> Result<InputMeta, EmptyInputError> {
192 Err(EmptyInputError::NotSupported)
193 }
194
195 async fn process_output<'a, 'b>(
196 &'a self,
197 _dbtx: &mut DatabaseTransaction<'b>,
198 _output: &'a EmptyOutput,
199 _out_point: OutPoint,
200 ) -> Result<TransactionItemAmounts, EmptyOutputError> {
201 Err(EmptyOutputError::NotSupported)
202 }
203
204 async fn output_status(
205 &self,
206 _dbtx: &mut DatabaseTransaction<'_>,
207 _out_point: OutPoint,
208 ) -> Option<EmptyOutputOutcome> {
209 None
210 }
211
212 async fn audit(
213 &self,
214 _dbtx: &mut DatabaseTransaction<'_>,
215 _audit: &mut Audit,
216 _module_instance_id: ModuleInstanceId,
217 ) {
218 }
219
220 fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
221 Vec::new()
222 }
223}
224
225impl Empty {
226 pub fn new(cfg: EmptyConfig) -> Empty {
228 Empty { cfg }
229 }
230}