fedimint_dummy_client/
db.rs1use std::io::Cursor;
2
3use fedimint_core::core::{ModuleInstanceId, OperationId};
4use fedimint_core::db::{DatabaseTransaction, IDatabaseTransactionOpsCoreTyped};
5use fedimint_core::encoding::{Decodable, Encodable};
6use fedimint_core::module::registry::ModuleDecoderRegistry;
7use fedimint_core::{impl_db_record, Amount, TransactionId};
8use strum_macros::EnumIter;
9use tracing::warn;
10
11use crate::states::DummyStateMachine;
12
13#[repr(u8)]
14#[derive(Clone, Debug, EnumIter)]
15pub enum DbKeyPrefix {
16 ClientFunds = 0x04,
17 ClientName = 0x50,
20}
21
22impl std::fmt::Display for DbKeyPrefix {
23 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24 write!(f, "{self:?}")
25 }
26}
27
28#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
29pub struct DummyClientFundsKeyV0;
30
31impl_db_record!(
32 key = DummyClientFundsKeyV0,
33 value = (),
34 db_prefix = DbKeyPrefix::ClientFunds,
35);
36
37#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
38pub struct DummyClientFundsKeyV1;
39
40impl_db_record!(
41 key = DummyClientFundsKeyV1,
42 value = Amount,
43 db_prefix = DbKeyPrefix::ClientFunds,
44);
45
46#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
47pub struct DummyClientNameKey;
48
49impl_db_record!(
50 key = DummyClientNameKey,
51 value = String,
52 db_prefix = DbKeyPrefix::ClientName,
53);
54
55pub async fn migrate_to_v1(
59 dbtx: &mut DatabaseTransaction<'_>,
60) -> anyhow::Result<Option<(Vec<(Vec<u8>, OperationId)>, Vec<(Vec<u8>, OperationId)>)>> {
61 if dbtx.remove_entry(&DummyClientFundsKeyV0).await.is_some() {
62 dbtx.insert_new_entry(&DummyClientFundsKeyV1, &Amount::from_sats(1000))
66 .await;
67 } else {
68 warn!("Dummy client did not have client funds, skipping database migration");
69 }
70
71 Ok(None)
72}
73
74pub(crate) fn get_v1_migrated_state(
76 operation_id: OperationId,
77 cursor: &mut Cursor<&[u8]>,
78) -> anyhow::Result<Option<(Vec<u8>, OperationId)>> {
79 let decoders = ModuleDecoderRegistry::default();
80 let dummy_sm_variant = u16::consensus_decode(cursor, &decoders)?;
81
82 if dummy_sm_variant != 5 {
85 return Ok(None);
86 }
87
88 let unreachable = Unreachable::consensus_decode(cursor, &decoders)?;
90 let new_state = DummyStateMachine::OutputDone(
91 unreachable.amount,
92 unreachable.txid,
93 unreachable.operation_id,
94 );
95 let bytes = new_state.consensus_encode_to_vec();
96 Ok(Some((bytes, operation_id)))
97}
98
99#[derive(Debug)]
100struct Unreachable {
101 _module_instance_id: ModuleInstanceId,
102 operation_id: OperationId,
103 txid: TransactionId,
104 amount: Amount,
105}
106
107impl Decodable for Unreachable {
108 fn consensus_decode<R: std::io::Read>(
109 reader: &mut R,
110 modules: &ModuleDecoderRegistry,
111 ) -> Result<Self, fedimint_core::encoding::DecodeError> {
112 let module_instance_id = ModuleInstanceId::consensus_decode(reader, modules)?;
113 let operation_id = OperationId::consensus_decode(reader, modules)?;
114 let txid = TransactionId::consensus_decode(reader, modules)?;
115 let amount = Amount::consensus_decode(reader, modules)?;
116
117 Ok(Unreachable {
118 _module_instance_id: module_instance_id,
119 operation_id,
120 txid,
121 amount,
122 })
123 }
124}