1use core::fmt;
2use std::ops;
3use std::str::FromStr;
4use std::time::SystemTime;
5
6use fedimint_client_module::module::init::recovery::RecoveryFromHistoryCommon;
7use fedimint_core::core::OperationId;
8use fedimint_core::encoding::{
9 Decodable, DecodeError, Encodable, decode_field_from_finite_reader,
10 decode_legacy_option_system_time_from_finite_reader,
11 decode_legacy_system_time_from_finite_reader, encode_legacy_option_system_time,
12 encode_legacy_system_time, with_decoding_context,
13};
14use fedimint_core::module::registry::ModuleDecoderRegistry;
15use fedimint_core::{TransactionId, impl_db_lookup, impl_db_record};
16use serde::{Deserialize, Serialize};
17use strum_macros::EnumIter;
18
19use crate::backup::WalletRecoveryState;
20
21#[derive(Clone, EnumIter, Debug)]
22pub enum DbKeyPrefix {
23 NextPegInTweakIndex = 0x2c,
24 PegInTweakIndex = 0x2d,
25 ClaimedPegIn = 0x2e,
26 RecoveryFinalized = 0x2f,
27 RecoveryState = 0x30,
28 SupportsSafeDeposit = 0x31,
29 PegInPoolCursor = 0x32,
30 ExternalReservedStart = 0xb0,
33 CoreInternalReservedStart = 0xd0,
36 CoreInternalReservedEnd = 0xff,
39}
40
41impl std::fmt::Display for DbKeyPrefix {
42 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43 write!(f, "{self:?}")
44 }
45}
46
47#[derive(
52 Copy,
53 Clone,
54 Debug,
55 Encodable,
56 Decodable,
57 Serialize,
58 Deserialize,
59 Default,
60 PartialEq,
61 Eq,
62 PartialOrd,
63 Ord,
64)]
65pub struct TweakIdx(pub u64);
66
67impl fmt::Display for TweakIdx {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.write_fmt(format_args!("TweakIdx({})", self.0))
70 }
71}
72
73impl FromStr for TweakIdx {
74 type Err = <u64 as FromStr>::Err;
75
76 fn from_str(s: &str) -> Result<Self, Self::Err> {
77 Ok(Self(FromStr::from_str(s)?))
78 }
79}
80
81impl TweakIdx {
82 #[must_use]
83 pub fn next(self) -> Self {
84 Self(self.0 + 1)
85 }
86
87 #[must_use]
88 pub fn prev(self) -> Option<Self> {
89 self.0.checked_sub(1).map(Self)
90 }
91
92 #[must_use]
93 pub fn advance(self, i: u64) -> Self {
94 Self(self.0 + i)
95 }
96
97 pub fn saturating_sub(&self, rhs: TweakIdx) -> u64 {
98 self.0.saturating_sub(rhs.0)
99 }
100}
101
102impl ops::Sub for TweakIdx {
103 type Output = u64;
104
105 fn sub(self, rhs: Self) -> Self::Output {
106 self.0 - rhs.0
107 }
108}
109
110#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
112pub struct NextPegInTweakIndexKey;
113
114impl_db_record!(
115 key = NextPegInTweakIndexKey,
116 value = TweakIdx,
117 db_prefix = DbKeyPrefix::NextPegInTweakIndex,
118);
119
120#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
123pub struct PegInTweakIndexKey(pub TweakIdx);
124
125#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
126pub struct PegInTweakIndexPrefix;
127
128#[derive(Clone, Debug, Serialize)]
129pub struct PegInTweakIndexData {
130 pub operation_id: OperationId,
132 pub creation_time: SystemTime,
134 pub last_check_time: Option<SystemTime>,
136 pub next_check_time: Option<SystemTime>,
138 pub claimed: Vec<bitcoin::OutPoint>,
140}
141
142impl Encodable for PegInTweakIndexData {
143 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
144 self.operation_id.consensus_encode(writer)?;
145 encode_legacy_system_time(&self.creation_time, writer)?;
146 encode_legacy_option_system_time(&self.last_check_time, writer)?;
147 encode_legacy_option_system_time(&self.next_check_time, writer)?;
148 self.claimed.consensus_encode(writer)
149 }
150}
151
152impl Decodable for PegInTweakIndexData {
153 fn consensus_decode_partial_from_finite_reader<D: std::io::Read>(
154 decoder: &mut D,
155 modules: &ModuleDecoderRegistry,
156 ) -> Result<Self, DecodeError> {
157 Ok(Self {
158 operation_id: decode_field_from_finite_reader(
159 decoder,
160 modules,
161 "Decoding named block field: PegInTweakIndexData{ ... operation_id ... }",
162 )?,
163 creation_time: with_decoding_context(
164 decode_legacy_system_time_from_finite_reader(decoder, modules),
165 "Decoding named block field: PegInTweakIndexData{ ... creation_time ... }",
166 )?,
167 last_check_time: with_decoding_context(
168 decode_legacy_option_system_time_from_finite_reader(decoder, modules),
169 "Decoding named block field: PegInTweakIndexData{ ... last_check_time ... }",
170 )?,
171 next_check_time: with_decoding_context(
172 decode_legacy_option_system_time_from_finite_reader(decoder, modules),
173 "Decoding named block field: PegInTweakIndexData{ ... next_check_time ... }",
174 )?,
175 claimed: decode_field_from_finite_reader(
176 decoder,
177 modules,
178 "Decoding named block field: PegInTweakIndexData{ ... claimed ... }",
179 )?,
180 })
181 }
182}
183
184impl_db_record!(
185 key = PegInTweakIndexKey,
186 value = PegInTweakIndexData,
187 db_prefix = DbKeyPrefix::PegInTweakIndex,
188);
189
190impl_db_lookup!(
191 key = PegInTweakIndexKey,
192 query_prefix = PegInTweakIndexPrefix
193);
194
195#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
196pub struct ClaimedPegInKey {
197 pub peg_in_index: TweakIdx,
198 pub btc_out_point: bitcoin::OutPoint,
199}
200
201#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
202pub struct ClaimedPegInPrefix;
203
204#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
205pub struct ClaimedPegInData {
206 pub claim_txid: TransactionId,
211 pub change: Vec<fedimint_core::OutPoint>,
212}
213
214impl_db_record!(
215 key = ClaimedPegInKey,
216 value = ClaimedPegInData,
217 db_prefix = DbKeyPrefix::ClaimedPegIn,
218 notify_on_modify = true,
219);
220impl_db_lookup!(key = ClaimedPegInKey, query_prefix = ClaimedPegInPrefix);
221
222#[derive(Debug, Clone, Encodable, Decodable, Serialize)]
223pub struct RecoveryFinalizedKey;
224
225#[derive(Debug, Clone, Encodable, Decodable)]
226pub struct RecoveryFinalizedKeyPrefix;
227
228impl_db_record!(
229 key = RecoveryFinalizedKey,
230 value = bool,
231 db_prefix = DbKeyPrefix::RecoveryFinalized,
232);
233
234#[derive(Debug, Clone, Encodable, Decodable, Serialize)]
235pub struct RecoveryStateKey;
236
237#[derive(Debug, Clone, Encodable, Decodable)]
238pub struct RestoreStateKeyPrefix;
239
240impl_db_record!(
241 key = RecoveryStateKey,
242 value = (WalletRecoveryState, RecoveryFromHistoryCommon),
243 db_prefix = DbKeyPrefix::RecoveryState,
244);
245
246#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
247pub struct SupportsSafeDepositKey;
248
249#[derive(Clone, Debug, Encodable, Decodable)]
250pub struct SupportsSafeDepositPrefix;
251
252impl_db_record!(
253 key = SupportsSafeDepositKey,
254 value = (),
255 db_prefix = DbKeyPrefix::SupportsSafeDeposit,
256);
257
258impl_db_lookup!(
259 key = SupportsSafeDepositKey,
260 query_prefix = SupportsSafeDepositPrefix
261);
262
263#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
270pub struct PegInPoolCursorKey;
271
272impl_db_record!(
273 key = PegInPoolCursorKey,
274 value = TweakIdx,
275 db_prefix = DbKeyPrefix::PegInPoolCursor,
276);