fedimint_dummy_client/
db.rs1use std::io::Cursor;
2
3use fedimint_core::core::OperationId;
4use fedimint_core::db::{DatabaseTransaction, IDatabaseTransactionOpsCoreTyped};
5use fedimint_core::encoding::{Decodable, Encodable};
6use fedimint_core::module::registry::ModuleDecoderRegistry;
7use fedimint_core::{Amount, TransactionId, impl_db_record};
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 ExternalReservedStart = 0xb0,
23 CoreInternalReservedStart = 0xd0,
26 CoreInternalReservedEnd = 0xff,
29}
30
31impl std::fmt::Display for DbKeyPrefix {
32 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
33 write!(f, "{self:?}")
34 }
35}
36
37#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
38pub struct DummyClientFundsKeyV0;
39
40impl_db_record!(
41 key = DummyClientFundsKeyV0,
42 value = (),
43 db_prefix = DbKeyPrefix::ClientFunds,
44);
45
46#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
47pub struct DummyClientFundsKeyV1;
48
49impl_db_record!(
50 key = DummyClientFundsKeyV1,
51 value = Amount,
52 db_prefix = DbKeyPrefix::ClientFunds,
53);
54
55#[derive(Debug, Clone, Encodable, Decodable, Eq, PartialEq, Hash)]
56pub struct DummyClientNameKey;
57
58impl_db_record!(
59 key = DummyClientNameKey,
60 value = String,
61 db_prefix = DbKeyPrefix::ClientName,
62);
63
64pub async fn migrate_to_v1(
68 dbtx: &mut DatabaseTransaction<'_>,
69) -> anyhow::Result<Option<(Vec<(Vec<u8>, OperationId)>, Vec<(Vec<u8>, OperationId)>)>> {
70 if dbtx.remove_entry(&DummyClientFundsKeyV0).await.is_some() {
71 dbtx.insert_new_entry(&DummyClientFundsKeyV1, &Amount::from_sats(1000))
75 .await;
76 } else {
77 warn!("Dummy client did not have client funds, skipping database migration");
78 }
79
80 Ok(None)
81}
82
83pub(crate) fn get_v1_migrated_state(
85 operation_id: OperationId,
86 cursor: &mut Cursor<&[u8]>,
87) -> anyhow::Result<Option<(Vec<u8>, OperationId)>> {
88 let decoders = ModuleDecoderRegistry::default();
89 let dummy_sm_variant = u16::consensus_decode_partial(cursor, &decoders)?;
90
91 if dummy_sm_variant != 5 {
94 return Ok(None);
95 }
96
97 let _unreachable_state_length = u16::consensus_decode_partial(cursor, &decoders)?;
98
99 let unreachable = Unreachable::consensus_decode_partial(cursor, &decoders)?;
101 let new_state = DummyStateMachine::OutputDone(
102 unreachable.amount,
103 unreachable.txid,
104 unreachable.operation_id,
105 );
106 let bytes = new_state.consensus_encode_to_vec();
107 Ok(Some((bytes, operation_id)))
108}
109
110#[derive(Debug)]
111struct Unreachable {
112 operation_id: OperationId,
113 txid: TransactionId,
114 amount: Amount,
115}
116
117impl Decodable for Unreachable {
118 fn consensus_decode_partial<R: std::io::Read>(
119 reader: &mut R,
120 modules: &ModuleDecoderRegistry,
121 ) -> Result<Self, fedimint_core::encoding::DecodeError> {
122 let operation_id = OperationId::consensus_decode_partial(reader, modules)?;
123 let txid = TransactionId::consensus_decode_partial(reader, modules)?;
124 let amount = Amount::consensus_decode_partial(reader, modules)?;
125
126 Ok(Unreachable {
127 operation_id,
128 txid,
129 amount,
130 })
131 }
132}