cdk_common/database/mint/
mod.rs

1//! CDK Database
2
3use std::collections::HashMap;
4
5use async_trait::async_trait;
6use cashu::{Amount, MintInfo};
7use uuid::Uuid;
8
9use super::Error;
10use crate::common::QuoteTTL;
11use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote};
12use crate::nuts::{
13    BlindSignature, CurrencyUnit, Id, MeltQuoteState, Proof, Proofs, PublicKey, State,
14};
15use crate::payment::PaymentIdentifier;
16
17#[cfg(feature = "auth")]
18mod auth;
19
20#[cfg(feature = "test")]
21pub mod test;
22
23#[cfg(feature = "auth")]
24pub use auth::{MintAuthDatabase, MintAuthTransaction};
25
26/// KeysDatabaseWriter
27#[async_trait]
28pub trait KeysDatabaseTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
29    /// Add Active Keyset
30    async fn set_active_keyset(&mut self, unit: CurrencyUnit, id: Id) -> Result<(), Error>;
31
32    /// Add [`MintKeySetInfo`]
33    async fn add_keyset_info(&mut self, keyset: MintKeySetInfo) -> Result<(), Error>;
34}
35
36/// Mint Keys Database trait
37#[async_trait]
38pub trait KeysDatabase {
39    /// Mint Keys Database Error
40    type Err: Into<Error> + From<Error>;
41
42    /// Beings a transaction
43    async fn begin_transaction<'a>(
44        &'a self,
45    ) -> Result<Box<dyn KeysDatabaseTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
46
47    /// Get Active Keyset
48    async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>;
49
50    /// Get all Active Keyset
51    async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err>;
52
53    /// Get [`MintKeySetInfo`]
54    async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>;
55
56    /// Get [`MintKeySetInfo`]s
57    async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
58}
59
60/// Mint Quote Database writer trait
61#[async_trait]
62pub trait QuotesTransaction<'a> {
63    /// Mint Quotes Database Error
64    type Err: Into<Error> + From<Error>;
65
66    /// Get [`MintMintQuote`] and lock it for update in this transaction
67    async fn get_mint_quote(&mut self, quote_id: &Uuid)
68        -> Result<Option<MintMintQuote>, Self::Err>;
69    /// Add [`MintMintQuote`]
70    async fn add_mint_quote(&mut self, quote: MintMintQuote) -> Result<(), Self::Err>;
71    /// Increment amount paid [`MintMintQuote`]
72    async fn increment_mint_quote_amount_paid(
73        &mut self,
74        quote_id: &Uuid,
75        amount_paid: Amount,
76        payment_id: String,
77    ) -> Result<Amount, Self::Err>;
78    /// Increment amount paid [`MintMintQuote`]
79    async fn increment_mint_quote_amount_issued(
80        &mut self,
81        quote_id: &Uuid,
82        amount_issued: Amount,
83    ) -> Result<Amount, Self::Err>;
84    /// Remove [`MintMintQuote`]
85    async fn remove_mint_quote(&mut self, quote_id: &Uuid) -> Result<(), Self::Err>;
86    /// Get [`mint::MeltQuote`] and lock it for update in this transaction
87    async fn get_melt_quote(
88        &mut self,
89        quote_id: &Uuid,
90    ) -> Result<Option<mint::MeltQuote>, Self::Err>;
91    /// Add [`mint::MeltQuote`]
92    async fn add_melt_quote(&mut self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
93
94    /// Updates the request lookup id for a melt quote
95    async fn update_melt_quote_request_lookup_id(
96        &mut self,
97        quote_id: &Uuid,
98        new_request_lookup_id: &PaymentIdentifier,
99    ) -> Result<(), Self::Err>;
100
101    /// Update [`mint::MeltQuote`] state
102    ///
103    /// It is expected for this function to fail if the state is already set to the new state
104    async fn update_melt_quote_state(
105        &mut self,
106        quote_id: &Uuid,
107        new_state: MeltQuoteState,
108        payment_proof: Option<String>,
109    ) -> Result<(MeltQuoteState, mint::MeltQuote), Self::Err>;
110    /// Remove [`mint::MeltQuote`]
111    async fn remove_melt_quote(&mut self, quote_id: &Uuid) -> Result<(), Self::Err>;
112    /// Get all [`MintMintQuote`]s and lock it for update in this transaction
113    async fn get_mint_quote_by_request(
114        &mut self,
115        request: &str,
116    ) -> Result<Option<MintMintQuote>, Self::Err>;
117
118    /// Get all [`MintMintQuote`]s
119    async fn get_mint_quote_by_request_lookup_id(
120        &mut self,
121        request_lookup_id: &PaymentIdentifier,
122    ) -> Result<Option<MintMintQuote>, Self::Err>;
123}
124
125/// Mint Quote Database trait
126#[async_trait]
127pub trait QuotesDatabase {
128    /// Mint Quotes Database Error
129    type Err: Into<Error> + From<Error>;
130
131    /// Get [`MintMintQuote`]
132    async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintMintQuote>, Self::Err>;
133
134    /// Get all [`MintMintQuote`]s
135    async fn get_mint_quote_by_request(
136        &self,
137        request: &str,
138    ) -> Result<Option<MintMintQuote>, Self::Err>;
139    /// Get all [`MintMintQuote`]s
140    async fn get_mint_quote_by_request_lookup_id(
141        &self,
142        request_lookup_id: &PaymentIdentifier,
143    ) -> Result<Option<MintMintQuote>, Self::Err>;
144    /// Get Mint Quotes
145    async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
146    /// Get [`mint::MeltQuote`]
147    async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err>;
148    /// Get all [`mint::MeltQuote`]s
149    async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
150}
151
152/// Mint Proof Transaction trait
153#[async_trait]
154pub trait ProofsTransaction<'a> {
155    /// Mint Proof Database Error
156    type Err: Into<Error> + From<Error>;
157
158    /// Add  [`Proofs`]
159    ///
160    /// Adds proofs to the database. The database should error if the proof already exits, with a
161    /// `AttemptUpdateSpentProof` if the proof is already spent or a `Duplicate` error otherwise.
162    async fn add_proofs(&mut self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
163    /// Updates the proofs to a given states and return the previous states
164    async fn update_proofs_states(
165        &mut self,
166        ys: &[PublicKey],
167        proofs_state: State,
168    ) -> Result<Vec<Option<State>>, Self::Err>;
169
170    /// Remove [`Proofs`]
171    async fn remove_proofs(
172        &mut self,
173        ys: &[PublicKey],
174        quote_id: Option<Uuid>,
175    ) -> Result<(), Self::Err>;
176}
177
178/// Mint Proof Database trait
179#[async_trait]
180pub trait ProofsDatabase {
181    /// Mint Proof Database Error
182    type Err: Into<Error> + From<Error>;
183
184    /// Get [`Proofs`] by ys
185    async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
186    /// Get ys by quote id
187    async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err>;
188    /// Get [`Proofs`] state
189    async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
190    /// Get [`Proofs`] by state
191    async fn get_proofs_by_keyset_id(
192        &self,
193        keyset_id: &Id,
194    ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
195}
196
197#[async_trait]
198/// Mint Signatures Transaction trait
199pub trait SignaturesTransaction<'a> {
200    /// Mint Signature Database Error
201    type Err: Into<Error> + From<Error>;
202
203    /// Add [`BlindSignature`]
204    async fn add_blind_signatures(
205        &mut self,
206        blinded_messages: &[PublicKey],
207        blind_signatures: &[BlindSignature],
208        quote_id: Option<Uuid>,
209    ) -> Result<(), Self::Err>;
210
211    /// Get [`BlindSignature`]s
212    async fn get_blind_signatures(
213        &mut self,
214        blinded_messages: &[PublicKey],
215    ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
216}
217
218#[async_trait]
219/// Mint Signatures Database trait
220pub trait SignaturesDatabase {
221    /// Mint Signature Database Error
222    type Err: Into<Error> + From<Error>;
223
224    /// Get [`BlindSignature`]s
225    async fn get_blind_signatures(
226        &self,
227        blinded_messages: &[PublicKey],
228    ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
229    /// Get [`BlindSignature`]s for keyset_id
230    async fn get_blind_signatures_for_keyset(
231        &self,
232        keyset_id: &Id,
233    ) -> Result<Vec<BlindSignature>, Self::Err>;
234    /// Get [`BlindSignature`]s for quote
235    async fn get_blind_signatures_for_quote(
236        &self,
237        quote_id: &Uuid,
238    ) -> Result<Vec<BlindSignature>, Self::Err>;
239}
240
241#[async_trait]
242/// Commit and Rollback
243pub trait DbTransactionFinalizer {
244    /// Mint Signature Database Error
245    type Err: Into<Error> + From<Error>;
246
247    /// Commits all the changes into the database
248    async fn commit(self: Box<Self>) -> Result<(), Self::Err>;
249
250    /// Rollbacks the write transaction
251    async fn rollback(self: Box<Self>) -> Result<(), Self::Err>;
252}
253
254/// Base database writer
255#[async_trait]
256pub trait Transaction<'a, Error>:
257    DbTransactionFinalizer<Err = Error>
258    + QuotesTransaction<'a, Err = Error>
259    + SignaturesTransaction<'a, Err = Error>
260    + ProofsTransaction<'a, Err = Error>
261{
262    /// Set [`QuoteTTL`]
263    async fn set_quote_ttl(&mut self, quote_ttl: QuoteTTL) -> Result<(), Error>;
264
265    /// Set [`MintInfo`]
266    async fn set_mint_info(&mut self, mint_info: MintInfo) -> Result<(), Error>;
267}
268
269/// Mint Database trait
270#[async_trait]
271pub trait Database<Error>:
272    QuotesDatabase<Err = Error> + ProofsDatabase<Err = Error> + SignaturesDatabase<Err = Error>
273{
274    /// Beings a transaction
275    async fn begin_transaction<'a>(
276        &'a self,
277    ) -> Result<Box<dyn Transaction<'a, Error> + Send + Sync + 'a>, Error>;
278
279    /// Get [`MintInfo`]
280    async fn get_mint_info(&self) -> Result<MintInfo, Error>;
281
282    /// Get [`QuoteTTL`]
283    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Error>;
284}