Skip to main content

fedimint_server/
db.rs

1use std::collections::BTreeSet;
2
3use bitcoin::hex::DisplayHex as _;
4use fedimint_core::db::{
5    DatabaseTransaction, IDatabaseTransactionOpsCore as _, MODULE_GLOBAL_PREFIX,
6};
7use fedimint_core::encoding::{Decodable, Encodable};
8use fedimint_core::impl_db_record;
9use futures::StreamExt as _;
10use strum::{EnumIter, IntoEnumIterator as _};
11
12#[repr(u8)]
13#[derive(Clone, EnumIter, Debug)]
14pub enum DbKeyPrefix {
15    AcceptedItem = 0x01,
16    AcceptedTransaction = 0x02,
17    SignedSessionOutcome = 0x04,
18    AlephUnits = 0x05,
19    // TODO: do we want to split the server DB into consensus/non-consensus?
20    ApiAnnouncements = 0x06,
21    ServerInfo = 0x07,
22    GuardianMetadata = 0x08,
23    PeerAvailability = 0x09,
24
25    DatabaseVersion = fedimint_core::db::DbKeyPrefix::DatabaseVersion as u8,
26    ClientBackup = fedimint_core::db::DbKeyPrefix::ClientBackup as u8,
27    Module = MODULE_GLOBAL_PREFIX,
28}
29
30pub(crate) async fn verify_server_db_integrity_dbtx(dbtx: &mut DatabaseTransaction<'_>) {
31    let prefixes: BTreeSet<u8> = DbKeyPrefix::iter().map(|prefix| prefix as u8).collect();
32
33    let mut records = dbtx.raw_find_by_prefix(&[]).await.expect("DB fail");
34    while let Some((k, v)) = records.next().await {
35        // We don't want to waste time checking these
36        if k[0] == DbKeyPrefix::Module as u8 {
37            break;
38        }
39
40        assert!(
41            prefixes.contains(&k[0]),
42            "Unexpected server db record found: {}: {}",
43            k.as_hex(),
44            v.as_hex()
45        );
46    }
47}
48
49impl std::fmt::Display for DbKeyPrefix {
50    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
51        write!(f, "{self:?}")
52    }
53}
54
55#[derive(Clone, Debug, Encodable, Decodable)]
56pub struct ServerInfoKey;
57
58#[derive(Clone, Debug, Encodable, Decodable)]
59pub struct ServerInfo {
60    /// The initial version that set up the consensus
61    pub init_version: String,
62    /// The last version that passed db migration checks
63    pub last_version: String,
64}
65
66impl_db_record!(
67    key = ServerInfoKey,
68    value = ServerInfo,
69    db_prefix = DbKeyPrefix::ServerInfo,
70    notify_on_modify = false,
71);