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 }