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}
33
34impl std::fmt::Display for DbKeyPrefix {
35 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
36 write!(f, "{self:?}")
37 }
38}
39
40#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
41pub struct BlockHashKey(pub BlockHash);
42
43#[derive(Clone, Debug, Encodable, Decodable)]
44pub struct BlockHashKeyPrefix;
45
46impl_db_record!(
47 key = BlockHashKey,
48 value = (),
49 db_prefix = DbKeyPrefix::BlockHash,
50);
51impl_db_lookup!(key = BlockHashKey, query_prefix = BlockHashKeyPrefix);
52
53#[derive(Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize)]
54pub struct UTXOKey(pub bitcoin::OutPoint);
55
56#[derive(Clone, Debug, Encodable, Decodable)]
57pub struct UTXOPrefixKey;
58
59impl_db_record!(
60 key = UTXOKey,
61 value = SpendableUTXO,
62 db_prefix = DbKeyPrefix::Utxo,
63);
64impl_db_lookup!(key = UTXOKey, query_prefix = UTXOPrefixKey);
65
66#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
67pub struct UnsignedTransactionKey(pub Txid);
68
69#[derive(Clone, Debug, Encodable, Decodable)]
70pub struct UnsignedTransactionPrefixKey;
71
72impl_db_record!(
73 key = UnsignedTransactionKey,
74 value = UnsignedTransaction,
75 db_prefix = DbKeyPrefix::UnsignedTransaction,
76);
77impl_db_lookup!(
78 key = UnsignedTransactionKey,
79 query_prefix = UnsignedTransactionPrefixKey
80);
81
82#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
83pub struct PendingTransactionKey(pub Txid);
84
85#[derive(Clone, Debug, Encodable, Decodable)]
86pub struct PendingTransactionPrefixKey;
87
88impl_db_record!(
89 key = PendingTransactionKey,
90 value = PendingTransaction,
91 db_prefix = DbKeyPrefix::PendingTransaction,
92);
93impl_db_lookup!(
94 key = PendingTransactionKey,
95 query_prefix = PendingTransactionPrefixKey
96);
97
98#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
99pub struct PegOutTxSignatureCI(pub Txid);
100
101#[derive(Clone, Debug, Encodable, Decodable)]
102pub struct PegOutTxSignatureCIPrefix;
103
104impl_db_record!(
105 key = PegOutTxSignatureCI,
106 value = Vec<Signature>,
107 db_prefix = DbKeyPrefix::PegOutTxSigCi,
108);
109impl_db_lookup!(
110 key = PegOutTxSignatureCI,
111 query_prefix = PegOutTxSignatureCIPrefix
112);
113
114#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
115pub struct PegOutBitcoinTransaction(pub fedimint_core::OutPoint);
116
117#[derive(Clone, Debug, Encodable, Decodable)]
118pub struct PegOutBitcoinTransactionPrefix;
119
120impl_db_record!(
121 key = PegOutBitcoinTransaction,
122 value = WalletOutputOutcome,
123 db_prefix = DbKeyPrefix::PegOutBitcoinOutPoint,
124);
125
126impl_db_lookup!(
127 key = PegOutBitcoinTransaction,
128 query_prefix = PegOutBitcoinTransactionPrefix
129);
130
131#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
132pub struct BlockCountVoteKey(pub PeerId);
133
134#[derive(Clone, Debug, Encodable, Decodable)]
135pub struct BlockCountVotePrefix;
136
137impl_db_record!(
138 key = BlockCountVoteKey,
139 value = u32,
140 db_prefix = DbKeyPrefix::BlockCountVote
141);
142
143impl_db_lookup!(key = BlockCountVoteKey, query_prefix = BlockCountVotePrefix);
144
145#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
146pub struct FeeRateVoteKey(pub PeerId);
147
148#[derive(Clone, Debug, Encodable, Decodable)]
149pub struct FeeRateVotePrefix;
150
151impl_db_record!(
152 key = FeeRateVoteKey,
153 value = fedimint_core::Feerate,
154 db_prefix = DbKeyPrefix::FeeRateVote
155);
156
157impl_db_lookup!(key = FeeRateVoteKey, query_prefix = FeeRateVotePrefix);
158
159#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
160pub struct ConsensusVersionVoteKey(pub PeerId);
161
162#[derive(Clone, Debug, Encodable, Decodable)]
163pub struct ConsensusVersionVotePrefix;
164
165impl_db_record!(
166 key = ConsensusVersionVoteKey,
167 value = ModuleConsensusVersion,
168 db_prefix = DbKeyPrefix::ConsensusVersionVote
169);
170
171impl_db_lookup!(
172 key = ConsensusVersionVoteKey,
173 query_prefix = ConsensusVersionVotePrefix
174);
175
176#[derive(Clone, Debug, Encodable, Decodable)]
177pub struct PegOutNonceKey;
178
179impl_db_record!(
180 key = PegOutNonceKey,
181 value = u64,
182 db_prefix = DbKeyPrefix::PegOutNonce
183);
184
185#[derive(Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize)]
186pub struct ClaimedPegInOutpointKey(pub OutPoint);
187
188#[derive(Clone, Debug, Encodable, Decodable)]
189pub struct ClaimedPegInOutpointPrefixKey;
190
191impl_db_record!(
192 key = ClaimedPegInOutpointKey,
193 value = (),
194 db_prefix = DbKeyPrefix::ClaimedPegInOutpoint,
195);
196impl_db_lookup!(
197 key = ClaimedPegInOutpointKey,
198 query_prefix = ClaimedPegInOutpointPrefixKey
199);
200
201pub async fn migrate_to_v1(
203 mut ctx: ServerModuleDbMigrationFnContext<'_, Wallet>,
204) -> Result<(), anyhow::Error> {
205 let outpoints = ctx
206 .get_typed_module_history_stream()
207 .await
208 .filter_map(|item| async {
209 match item {
210 ModuleHistoryItem::Input(input) => {
211 let outpoint = input
212 .maybe_v0_ref()
213 .expect("can only support V0 wallet inputs")
214 .0
215 .outpoint();
216
217 Some(outpoint)
218 }
219 ModuleHistoryItem::Output(_) | ModuleHistoryItem::ConsensusItem(_) => None,
220 }
221 })
222 .collect::<Vec<_>>()
223 .await;
224
225 let mut dbtx = ctx.dbtx();
226 for outpoint in outpoints {
227 dbtx.insert_new_entry(&ClaimedPegInOutpointKey(outpoint), &())
228 .await;
229 }
230
231 Ok(())
232}
233
234#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
235pub struct UnspentTxOutKey(pub bitcoin::OutPoint);
236
237#[derive(Clone, Debug, Encodable, Decodable)]
238pub struct UnspentTxOutPrefix;
239
240impl_db_record!(
241 key = UnspentTxOutKey,
242 value = TxOut,
243 db_prefix = DbKeyPrefix::UnspentTxOut,
244);
245impl_db_lookup!(key = UnspentTxOutKey, query_prefix = UnspentTxOutPrefix);
246
247#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
248pub struct ConsensusVersionVotingActivationKey;
249
250#[derive(Clone, Debug, Encodable, Decodable)]
251pub struct ConsensusVersionVotingActivationPrefix;
252
253impl_db_record!(
254 key = ConsensusVersionVotingActivationKey,
255 value = (),
256 db_prefix = DbKeyPrefix::ConsensusVersionVotingActivation,
257);
258impl_db_lookup!(
259 key = ConsensusVersionVotingActivationKey,
260 query_prefix = ConsensusVersionVotingActivationPrefix
261);