fedimint_unknown_server/
lib.rs

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};
21use fedimint_server_core::config::PeerHandleOps;
22use fedimint_server_core::migration::ServerModuleDbMigrationFn;
23use fedimint_server_core::{
24    ConfigGenModuleArgs, ServerModule, ServerModuleInit, ServerModuleInitArgs,
25};
26pub use fedimint_unknown_common as common;
27use fedimint_unknown_common::config::{
28    UnknownClientConfig, UnknownConfig, UnknownConfigConsensus, UnknownConfigPrivate,
29};
30use fedimint_unknown_common::{
31    MODULE_CONSENSUS_VERSION, UnknownCommonInit, UnknownConsensusItem, UnknownInput,
32    UnknownInputError, UnknownModuleTypes, UnknownOutput, UnknownOutputError, UnknownOutputOutcome,
33};
34pub mod db;
35
36/// Generates the module
37#[derive(Debug, Clone)]
38pub struct UnknownInit;
39
40// TODO: Boilerplate-code
41impl ModuleInit for UnknownInit {
42    type Common = UnknownCommonInit;
43
44    /// Dumps all database items for debugging
45    async fn dump_database(
46        &self,
47        _dbtx: &mut DatabaseTransaction<'_>,
48        _prefix_names: Vec<String>,
49    ) -> Box<dyn Iterator<Item = (String, Box<dyn erased_serde::Serialize + Send>)> + '_> {
50        Box::new(vec![].into_iter())
51    }
52}
53
54/// Implementation of server module non-consensus functions
55#[async_trait]
56impl ServerModuleInit for UnknownInit {
57    type Module = Unknown;
58
59    /// Returns the version of this module
60    fn versions(&self, _core: CoreConsensusVersion) -> &[ModuleConsensusVersion] {
61        &[MODULE_CONSENSUS_VERSION]
62    }
63
64    fn supported_api_versions(&self) -> SupportedModuleApiVersions {
65        SupportedModuleApiVersions::from_raw(
66            (CORE_CONSENSUS_VERSION.major, CORE_CONSENSUS_VERSION.minor),
67            (
68                MODULE_CONSENSUS_VERSION.major,
69                MODULE_CONSENSUS_VERSION.minor,
70            ),
71            &[(0, 0)],
72        )
73    }
74
75    /// Initialize the module
76    async fn init(&self, args: &ServerModuleInitArgs<Self>) -> anyhow::Result<Self::Module> {
77        Ok(Unknown::new(args.cfg().to_typed()?))
78    }
79
80    /// Generates configs for all peers in a trusted manner for testing
81    fn trusted_dealer_gen(
82        &self,
83        peers: &[PeerId],
84        _args: &ConfigGenModuleArgs,
85    ) -> BTreeMap<PeerId, ServerModuleConfig> {
86        // Generate a config for each peer
87        peers
88            .iter()
89            .map(|&peer| {
90                let config = UnknownConfig {
91                    private: UnknownConfigPrivate,
92                    consensus: UnknownConfigConsensus {},
93                };
94                (peer, config.to_erased())
95            })
96            .collect()
97    }
98
99    /// Generates configs for all peers in an untrusted manner
100    async fn distributed_gen(
101        &self,
102        _peers: &(dyn PeerHandleOps + Send + Sync),
103        _args: &ConfigGenModuleArgs,
104    ) -> anyhow::Result<ServerModuleConfig> {
105        Ok(UnknownConfig {
106            private: UnknownConfigPrivate,
107            consensus: UnknownConfigConsensus {},
108        }
109        .to_erased())
110    }
111
112    /// Converts the consensus config into the client config
113    fn get_client_config(
114        &self,
115        config: &ServerModuleConsensusConfig,
116    ) -> anyhow::Result<UnknownClientConfig> {
117        let _config = UnknownConfigConsensus::from_erased(config)?;
118        Ok(UnknownClientConfig {})
119    }
120
121    fn validate_config(
122        &self,
123        _identity: &PeerId,
124        _config: ServerModuleConfig,
125    ) -> anyhow::Result<()> {
126        Ok(())
127    }
128
129    /// DB migrations to move from old to newer versions
130    fn get_database_migrations(
131        &self,
132    ) -> BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<Unknown>> {
133        let mut migrations: BTreeMap<DatabaseVersion, ServerModuleDbMigrationFn<_>> =
134            BTreeMap::new();
135        // Unknown module prior to v0.5.0 had a `DATABASE_VERSION` of 1, so we must
136        // insert a no-op migration to ensure that upgrades work.
137        migrations.insert(DatabaseVersion(0), Box::new(|_| Box::pin(async { Ok(()) })));
138        migrations
139    }
140}
141
142/// Unknown module
143#[derive(Debug)]
144pub struct Unknown {
145    pub cfg: UnknownConfig,
146}
147
148/// Implementation of consensus for the server module
149#[async_trait]
150impl ServerModule for Unknown {
151    /// Define the consensus types
152    type Common = UnknownModuleTypes;
153    type Init = UnknownInit;
154
155    async fn consensus_proposal(
156        &self,
157        _dbtx: &mut DatabaseTransaction<'_>,
158    ) -> Vec<UnknownConsensusItem> {
159        Vec::new()
160    }
161
162    async fn process_consensus_item<'a, 'b>(
163        &'a self,
164        _dbtx: &mut DatabaseTransaction<'b>,
165        _consensus_item: UnknownConsensusItem,
166        _peer_id: PeerId,
167    ) -> anyhow::Result<()> {
168        // WARNING: `process_consensus_item` should return an `Err` for items that do
169        // not change any internal consensus state. Failure to do so, will result in an
170        // (potentially significantly) increased consensus history size.
171        // If you are using this code as a template,
172        // make sure to read the [`ServerModule::process_consensus_item`] documentation,
173        bail!("The unknown module does not use consensus items");
174    }
175
176    async fn process_input<'a, 'b, 'c>(
177        &'a self,
178        _dbtx: &mut DatabaseTransaction<'c>,
179        _input: &'b UnknownInput,
180        _in_point: InPoint,
181    ) -> Result<InputMeta, UnknownInputError> {
182        unreachable!();
183    }
184
185    async fn process_output<'a, 'b>(
186        &'a self,
187        _dbtx: &mut DatabaseTransaction<'b>,
188        _output: &'a UnknownOutput,
189        _out_point: OutPoint,
190    ) -> Result<TransactionItemAmounts, UnknownOutputError> {
191        unreachable!();
192    }
193
194    async fn output_status(
195        &self,
196        _dbtx: &mut DatabaseTransaction<'_>,
197        _out_point: OutPoint,
198    ) -> Option<UnknownOutputOutcome> {
199        unreachable!()
200    }
201
202    async fn audit(
203        &self,
204        _dbtx: &mut DatabaseTransaction<'_>,
205        _audit: &mut Audit,
206        _module_instance_id: ModuleInstanceId,
207    ) {
208    }
209
210    fn api_endpoints(&self) -> Vec<ApiEndpoint<Self>> {
211        Vec::new()
212    }
213}
214
215impl Unknown {
216    /// Create new module instance
217    pub fn new(cfg: UnknownConfig) -> Unknown {
218        Unknown { cfg }
219    }
220}