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};
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 fn supported_api_versions(&self) -> SupportedModuleApiVersions {
91 SupportedModuleApiVersions::from_raw(
92 (CORE_CONSENSUS_VERSION.major, CORE_CONSENSUS_VERSION.minor),
93 (
94 MODULE_CONSENSUS_VERSION.major,
95 MODULE_CONSENSUS_VERSION.minor,
96 ),
97 &[(0, 0)],
98 )
99 }
100
101 async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module> {
103 Ok(Empty::new(args.cfg().to_typed()?))
104 }
105
106 fn trusted_dealer_gen(
108 &self,
109 peers: &[PeerId],
110 _args: &ConfigGenModuleArgs,
111 ) -> BTreeMap<PeerId, ServerModuleConfig> {
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 _args: &ConfigGenModuleArgs,
130 ) -> anyhow::Result<ServerModuleConfig> {
131 Ok(EmptyConfig {
132 private: EmptyConfigPrivate,
133 consensus: EmptyConfigConsensus {},
134 }
135 .to_erased())
136 }
137
138 fn get_client_config(
140 &self,
141 config: &ServerModuleConsensusConfig,
142 ) -> anyhow::Result<EmptyClientConfig> {
143 let _config = EmptyConfigConsensus::from_erased(config)?;
144 Ok(EmptyClientConfig {})
145 }
146
147 fn validate_config(
148 &self,
149 _identity: &PeerId,
150 _config: ServerModuleConfig,
151 ) -> anyhow::Result<()> {
152 Ok(())
153 }
154
155 fn get_database_migrations(
157 &self,
158 ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Empty>> {
159 BTreeMap::new()
160 }
161}
162
163#[derive(Debug)]
165pub struct Empty {
166 pub cfg: EmptyConfig,
167}
168
169#[async_trait]
171impl ServerModule for Empty {
172 type Common = EmptyModuleTypes;
174 type Init = EmptyInit;
175
176 async fn consensus_proposal(
177 &self,
178 _dbtx: &mut DatabaseTransaction<'_>,
179 ) -> Vec<EmptyConsensusItem> {
180 Vec::new()
181 }
182
183 async fn process_consensus_item<'a, 'b>(
184 &'a self,
185 _dbtx: &mut DatabaseTransaction<'b>,
186 _consensus_item: EmptyConsensusItem,
187 _peer_id: PeerId,
188 ) -> anyhow::Result<()> {
189 bail!("The empty module does not use consensus items");
195 }
196
197 async fn process_input<'a, 'b, 'c>(
198 &'a self,
199 _dbtx: &mut DatabaseTransaction<'c>,
200 _input: &'b EmptyInput,
201 _in_point: InPoint,
202 ) -> Result<InputMeta, EmptyInputError> {
203 Err(EmptyInputError::NotSupported)
204 }
205
206 async fn process_output<'a, 'b>(
207 &'a self,
208 _dbtx: &mut DatabaseTransaction<'b>,
209 _output: &'a EmptyOutput,
210 _out_point: OutPoint,
211 ) -> Result<TransactionItemAmounts, EmptyOutputError> {
212 Err(EmptyOutputError::NotSupported)
213 }
214
215 async fn output_status(
216 &self,
217 _dbtx: &mut DatabaseTransaction<'_>,
218 _out_point: OutPoint,
219 ) -> Option<EmptyOutputOutcome> {
220 None
221 }
222
223 async fn audit(
224 &self,
225 _dbtx: &mut DatabaseTransaction<'_>,
226 _audit: &mut Audit,
227 _module_instance_id: ModuleInstanceId,
228 ) {
229 }
230
231 fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
232 Vec::new()
233 }
234}
235
236impl Empty {
237 pub fn new(cfg: EmptyConfig) -> Empty {
239 Empty { cfg }
240 }
241}