lib.rs
  1  #![deny(clippy::pedantic)]
  2  #![allow(clippy::module_name_repetitions)]
  3  #![allow(clippy::must_use_candidate)]
  4  
  5  use std::collections::BTreeMap;
  6  
  7  use anyhow::bail;
  8  use async_trait::async_trait;
  9  use fedimint_core::config::{
 10      ConfigGenModuleParams, DkgResult, ServerModuleConfig, ServerModuleConsensusConfig,
 11      TypedServerModuleConfig, TypedServerModuleConsensusConfig,
 12  };
 13  use fedimint_core::core::ModuleInstanceId;
 14  use fedimint_core::db::{CoreMigrationFn, DatabaseTransaction, DatabaseVersion};
 15  use fedimint_core::module::audit::Audit;
 16  use fedimint_core::module::{
 17      ApiEndpoint, CoreConsensusVersion, InputMeta, ModuleConsensusVersion, ModuleInit, PeerHandle,
 18      ServerModuleInit, ServerModuleInitArgs, SupportedModuleApiVersions, TransactionItemAmount,
 19      CORE_CONSENSUS_VERSION,
 20  };
 21  use fedimint_core::server::DynServerModule;
 22  use fedimint_core::{push_db_pair_items, OutPoint, PeerId, ServerModule};
 23  use fedimint_empty_common::config::{
 24      EmptyClientConfig, EmptyConfig, EmptyConfigConsensus, EmptyConfigLocal, EmptyConfigPrivate,
 25      EmptyGenParams,
 26  };
 27  use fedimint_empty_common::{
 28      EmptyCommonInit, EmptyConsensusItem, EmptyInput, EmptyInputError, EmptyModuleTypes,
 29      EmptyOutput, EmptyOutputError, EmptyOutputOutcome, MODULE_CONSENSUS_VERSION,
 30  };
 31  use futures::StreamExt;
 32  use strum::IntoEnumIterator;
 33  
 34  use crate::db::{DbKeyPrefix, EmptyExampleKeyPrefix};
 35  
 36  pub mod db;
 37  
 38  /// Generates the module
 39  #[derive(Debug, Clone)]
 40  pub struct EmptyInit;
 41  
 42  // TODO: Boilerplate-code
 43  impl ModuleInit for EmptyInit {
 44      type Common = EmptyCommonInit;
 45  
 46      /// Dumps all database items for debugging
 47      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          // TODO: Boilerplate-code
 53          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  /// Implementation of server module non-consensus functions
 78  #[async_trait]
 79  impl ServerModuleInit for EmptyInit {
 80      type Params = EmptyGenParams;
 81  
 82      /// Returns the version of this module
 83      fn versions(&self, _core: CoreConsensusVersion) -> &[ModuleConsensusVersion] {
 84          &[MODULE_CONSENSUS_VERSION]
 85      }
 86  
 87      fn supported_api_versions(&self) -> SupportedModuleApiVersions {
 88          SupportedModuleApiVersions::from_raw(
 89              (CORE_CONSENSUS_VERSION.major, CORE_CONSENSUS_VERSION.minor),
 90              (
 91                  MODULE_CONSENSUS_VERSION.major,
 92                  MODULE_CONSENSUS_VERSION.minor,
 93              ),
 94              &[(0, 0)],
 95          )
 96      }
 97  
 98      /// Initialize the module
 99      async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<DynServerModule> {
100          Ok(Empty::new(args.cfg().to_typed()?).into())
101      }
102  
103      /// Generates configs for all peers in a trusted manner for testing
104      fn trusted_dealer_gen(
105          &self,
106          peers: &[PeerId],
107          params: &ConfigGenModuleParams,
108      ) -> BTreeMap<PeerId, ServerModuleConfig> {
109          let _params = self.parse_params(params).unwrap();
110          // Generate a config for each peer
111          peers
112              .iter()
113              .map(|&peer| {
114                  let config = EmptyConfig {
115                      local: EmptyConfigLocal {},
116                      private: EmptyConfigPrivate,
117                      consensus: EmptyConfigConsensus {},
118                  };
119                  (peer, config.to_erased())
120              })
121              .collect()
122      }
123  
124      /// Generates configs for all peers in an untrusted manner
125      async fn distributed_gen(
126          &self,
127          _peers: &PeerHandle,
128          params: &ConfigGenModuleParams,
129      ) -> DkgResult<ServerModuleConfig> {
130          let _params = self.parse_params(params).unwrap();
131  
132          Ok(EmptyConfig {
133              local: EmptyConfigLocal {},
134              private: EmptyConfigPrivate,
135              consensus: EmptyConfigConsensus {},
136          }
137          .to_erased())
138      }
139  
140      /// Converts the consensus config into the client config
141      fn get_client_config(
142          &self,
143          config: &ServerModuleConsensusConfig,
144      ) -> anyhow::Result<EmptyClientConfig> {
145          let _config = EmptyConfigConsensus::from_erased(config)?;
146          Ok(EmptyClientConfig {})
147      }
148  
149      fn validate_config(
150          &self,
151          _identity: &PeerId,
152          _config: ServerModuleConfig,
153      ) -> anyhow::Result<()> {
154          Ok(())
155      }
156  
157      /// DB migrations to move from old to newer versions
158      fn get_database_migrations(&self) -> BTreeMap<DatabaseVersion, CoreMigrationFn> {
159          BTreeMap::new()
160      }
161  }
162  
163  /// Empty module
164  #[derive(Debug)]
165  pub struct Empty {
166      pub cfg: EmptyConfig,
167  }
168  
169  /// Implementation of consensus for the server module
170  #[async_trait]
171  impl ServerModule for Empty {
172      /// Define the consensus types
173      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          // WARNING: `process_consensus_item` should return an `Err` for items that do
190          // not change any internal consensus state. Failure to do so, will result in an
191          // (potentially significantly) increased consensus history size.
192          // If you are using this code as a template,
193          // make sure to read the [`ServerModule::process_consensus_item`] documentation,
194          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      ) -> 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<TransactionItemAmount, 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  
235  impl Empty {
236      /// Create new module instance
237      pub fn new(cfg: EmptyConfig) -> Empty {
238          Empty { cfg }
239      }
240  }