1use bitcoin::secp256k1::ecdsa::Signature;
2use bitcoin::{BlockHash, OutPoint, TxOut, Txid};
3use fedimint_core::db::IDatabaseTransactionOpsCoreTyped;
4use fedimint_core::encoding::{Decodable, Encodable};
5use fedimint_core::module::ModuleConsensusVersion;
6use fedimint_core::{PeerId, impl_db_lookup, impl_db_record};
7use fedimint_server_core::migration::{
8 ModuleHistoryItem, ServerModuleDbMigrationFnContext, ServerModuleDbMigrationFnContextExt as _,
9};
10use futures::StreamExt;
11use serde::Serialize;
12use strum_macros::EnumIter;
13
14use crate::{PendingTransaction, SpendableUTXO, UnsignedTransaction, Wallet, WalletOutputOutcome};
15
16#[repr(u8)]
17#[derive(Clone, EnumIter, Debug)]
18pub enum DbKeyPrefix {
19 BlockHash = 0x30,
20 Utxo = 0x31,
21 BlockCountVote = 0x32,
22 FeeRateVote = 0x33,
23 UnsignedTransaction = 0x34,
24 PendingTransaction = 0x35,
25 PegOutTxSigCi = 0x36,
26 PegOutBitcoinOutPoint = 0x37,
27 PegOutNonce = 0x38,
28 ClaimedPegInOutpoint = 0x39,
29 ConsensusVersionVote = 0x40,
30 UnspentTxOut = 0x41,
31 ConsensusVersionVotingActivation = 0x42,
32 BlockHashByHeight = 0x43,
36}
37
38impl std::fmt::Display for DbKeyPrefix {
39 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40 write!(f, "{self:?}")
41 }
42}
43
44#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
45pub struct BlockHashKey(pub BlockHash);
46
47#[derive(Clone, Debug, Encodable, Decodable)]
48pub struct BlockHashKeyPrefix;
49
50impl_db_record!(
51 key = BlockHashKey,
52 value = (),
53 db_prefix = DbKeyPrefix::BlockHash,
54);
55impl_db_lookup!(key = BlockHashKey, query_prefix = BlockHashKeyPrefix);
56
57#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
60pub struct BlockHashByHeightKey(pub u32);
61
62#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
63pub struct BlockHashByHeightValue(pub BlockHash);
64
65#[derive(Clone, Debug, Encodable, Decodable)]
66pub struct BlockHashByHeightKeyPrefix;
67
68impl_db_record!(
69 key = BlockHashByHeightKey,
70 value = BlockHashByHeightValue,
71 db_prefix = DbKeyPrefix::BlockHashByHeight,
72);
73impl_db_lookup!(
74 key = BlockHashByHeightKey,
75 query_prefix = BlockHashByHeightKeyPrefix
76);
77
78#[derive(Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize)]
79pub struct UTXOKey(pub bitcoin::OutPoint);
80
81#[derive(Clone, Debug, Encodable, Decodable)]
82pub struct UTXOPrefixKey;
83
84impl_db_record!(
85 key = UTXOKey,
86 value = SpendableUTXO,
87 db_prefix = DbKeyPrefix::Utxo,
88);
89impl_db_lookup!(key = UTXOKey, query_prefix = UTXOPrefixKey);
90
91#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
92pub struct UnsignedTransactionKey(pub Txid);
93
94#[derive(Clone, Debug, Encodable, Decodable)]
95pub struct UnsignedTransactionPrefixKey;
96
97impl_db_record!(
98 key = UnsignedTransactionKey,
99 value = UnsignedTransaction,
100 db_prefix = DbKeyPrefix::UnsignedTransaction,
101);
102impl_db_lookup!(
103 key = UnsignedTransactionKey,
104 query_prefix = UnsignedTransactionPrefixKey
105);
106
107#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
108pub struct PendingTransactionKey(pub Txid);
109
110#[derive(Clone, Debug, Encodable, Decodable)]
111pub struct PendingTransactionPrefixKey;
112
113impl_db_record!(
114 key = PendingTransactionKey,
115 value = PendingTransaction,
116 db_prefix = DbKeyPrefix::PendingTransaction,
117);
118impl_db_lookup!(
119 key = PendingTransactionKey,
120 query_prefix = PendingTransactionPrefixKey
121);
122
123#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
124pub struct PegOutTxSignatureCI(pub Txid);
125
126#[derive(Clone, Debug, Encodable, Decodable)]
127pub struct PegOutTxSignatureCIPrefix;
128
129impl_db_record!(
130 key = PegOutTxSignatureCI,
131 value = Vec<Signature>,
132 db_prefix = DbKeyPrefix::PegOutTxSigCi,
133);
134impl_db_lookup!(
135 key = PegOutTxSignatureCI,
136 query_prefix = PegOutTxSignatureCIPrefix
137);
138
139#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
140pub struct PegOutBitcoinTransaction(pub fedimint_core::OutPoint);
141
142#[derive(Clone, Debug, Encodable, Decodable)]
143pub struct PegOutBitcoinTransactionPrefix;
144
145impl_db_record!(
146 key = PegOutBitcoinTransaction,
147 value = WalletOutputOutcome,
148 db_prefix = DbKeyPrefix::PegOutBitcoinOutPoint,
149);
150
151impl_db_lookup!(
152 key = PegOutBitcoinTransaction,
153 query_prefix = PegOutBitcoinTransactionPrefix
154);
155
156#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
157pub struct BlockCountVoteKey(pub PeerId);
158
159#[derive(Clone, Debug, Encodable, Decodable)]
160pub struct BlockCountVotePrefix;
161
162impl_db_record!(
163 key = BlockCountVoteKey,
164 value = u32,
165 db_prefix = DbKeyPrefix::BlockCountVote
166);
167
168impl_db_lookup!(key = BlockCountVoteKey, query_prefix = BlockCountVotePrefix);
169
170#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
171pub struct FeeRateVoteKey(pub PeerId);
172
173#[derive(Clone, Debug, Encodable, Decodable)]
174pub struct FeeRateVotePrefix;
175
176impl_db_record!(
177 key = FeeRateVoteKey,
178 value = fedimint_core::Feerate,
179 db_prefix = DbKeyPrefix::FeeRateVote
180);
181
182impl_db_lookup!(key = FeeRateVoteKey, query_prefix = FeeRateVotePrefix);
183
184#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
185pub struct ConsensusVersionVoteKey(pub PeerId);
186
187#[derive(Clone, Debug, Encodable, Decodable)]
188pub struct ConsensusVersionVotePrefix;
189
190impl_db_record!(
191 key = ConsensusVersionVoteKey,
192 value = ModuleConsensusVersion,
193 db_prefix = DbKeyPrefix::ConsensusVersionVote
194);
195
196impl_db_lookup!(
197 key = ConsensusVersionVoteKey,
198 query_prefix = ConsensusVersionVotePrefix
199);
200
201#[derive(Clone, Debug, Encodable, Decodable)]
202pub struct PegOutNonceKey;
203
204impl_db_record!(
205 key = PegOutNonceKey,
206 value = u64,
207 db_prefix = DbKeyPrefix::PegOutNonce
208);
209
210#[derive(Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize)]
211pub struct ClaimedPegInOutpointKey(pub OutPoint);
212
213#[derive(Clone, Debug, Encodable, Decodable)]
214pub struct ClaimedPegInOutpointPrefixKey;
215
216impl_db_record!(
217 key = ClaimedPegInOutpointKey,
218 value = (),
219 db_prefix = DbKeyPrefix::ClaimedPegInOutpoint,
220);
221impl_db_lookup!(
222 key = ClaimedPegInOutpointKey,
223 query_prefix = ClaimedPegInOutpointPrefixKey
224);
225
226pub async fn migrate_to_v1(
228 mut ctx: ServerModuleDbMigrationFnContext<'_, Wallet>,
229) -> Result<(), anyhow::Error> {
230 let outpoints = ctx
231 .get_typed_module_history_stream()
232 .await
233 .filter_map(|item| async {
234 match item {
235 ModuleHistoryItem::Input(input) => {
236 let outpoint = input
237 .maybe_v0_ref()
238 .expect("can only support V0 wallet inputs")
239 .0
240 .outpoint();
241
242 Some(outpoint)
243 }
244 ModuleHistoryItem::Output(_) | ModuleHistoryItem::ConsensusItem(_) => None,
245 }
246 })
247 .collect::<Vec<_>>()
248 .await;
249
250 let mut dbtx = ctx.dbtx();
251 for outpoint in outpoints {
252 dbtx.insert_new_entry(&ClaimedPegInOutpointKey(outpoint), &())
253 .await;
254 }
255
256 Ok(())
257}
258
259#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
260pub struct UnspentTxOutKey(pub bitcoin::OutPoint);
261
262#[derive(Clone, Debug, Encodable, Decodable)]
263pub struct UnspentTxOutPrefix;
264
265impl_db_record!(
266 key = UnspentTxOutKey,
267 value = TxOut,
268 db_prefix = DbKeyPrefix::UnspentTxOut,
269);
270impl_db_lookup!(key = UnspentTxOutKey, query_prefix = UnspentTxOutPrefix);
271
272#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
273pub struct ConsensusVersionVotingActivationKey;
274
275#[derive(Clone, Debug, Encodable, Decodable)]
276pub struct ConsensusVersionVotingActivationPrefix;
277
278impl_db_record!(
279 key = ConsensusVersionVotingActivationKey,
280 value = (),
281 db_prefix = DbKeyPrefix::ConsensusVersionVotingActivation,
282);
283impl_db_lookup!(
284 key = ConsensusVersionVotingActivationKey,
285 query_prefix = ConsensusVersionVotingActivationPrefix
286);