cdk_common/database/mint/
mod.rs

1//! CDK Database
2
3use std::collections::HashMap;
4
5use async_trait::async_trait;
6use cashu::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, MintQuoteState, Proof, Proofs, PublicKey,
14    State,
15};
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_or_replace_mint_quote(&mut self, quote: MintMintQuote) -> Result<(), Self::Err>;
71    /// Update state of [`MintMintQuote`]
72    async fn update_mint_quote_state(
73        &mut self,
74        quote_id: &Uuid,
75        state: MintQuoteState,
76    ) -> Result<MintQuoteState, Self::Err>;
77    /// Remove [`MintMintQuote`]
78    async fn remove_mint_quote(&mut self, quote_id: &Uuid) -> Result<(), Self::Err>;
79    /// Get [`mint::MeltQuote`] and lock it for update in this transaction
80    async fn get_melt_quote(
81        &mut self,
82        quote_id: &Uuid,
83    ) -> Result<Option<mint::MeltQuote>, Self::Err>;
84    /// Add [`mint::MeltQuote`]
85    async fn add_melt_quote(&mut self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
86
87    /// Updates the request lookup id for a melt quote
88    async fn update_melt_quote_request_lookup_id(
89        &mut self,
90        quote_id: &Uuid,
91        new_request_lookup_id: &str,
92    ) -> Result<(), Self::Err>;
93
94    /// Update [`mint::MeltQuote`] state
95    ///
96    /// It is expected for this function to fail if the state is already set to the new state
97    async fn update_melt_quote_state(
98        &mut self,
99        quote_id: &Uuid,
100        new_state: MeltQuoteState,
101    ) -> Result<(MeltQuoteState, mint::MeltQuote), Self::Err>;
102    /// Remove [`mint::MeltQuote`]
103    async fn remove_melt_quote(&mut self, quote_id: &Uuid) -> Result<(), Self::Err>;
104    /// Get all [`MintMintQuote`]s and lock it for update in this transaction
105    async fn get_mint_quote_by_request(
106        &mut self,
107        request: &str,
108    ) -> Result<Option<MintMintQuote>, Self::Err>;
109}
110
111/// Mint Quote Database trait
112#[async_trait]
113pub trait QuotesDatabase {
114    /// Mint Quotes Database Error
115    type Err: Into<Error> + From<Error>;
116
117    /// Get [`MintMintQuote`]
118    async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintMintQuote>, Self::Err>;
119
120    /// Get all [`MintMintQuote`]s
121    async fn get_mint_quote_by_request(
122        &self,
123        request: &str,
124    ) -> Result<Option<MintMintQuote>, Self::Err>;
125    /// Get all [`MintMintQuote`]s
126    async fn get_mint_quote_by_request_lookup_id(
127        &self,
128        request_lookup_id: &str,
129    ) -> Result<Option<MintMintQuote>, Self::Err>;
130    /// Get Mint Quotes
131    async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
132    /// Get Mint Quotes with state
133    async fn get_mint_quotes_with_state(
134        &self,
135        state: MintQuoteState,
136    ) -> Result<Vec<MintMintQuote>, Self::Err>;
137    /// Get [`mint::MeltQuote`]
138    async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err>;
139    /// Get all [`mint::MeltQuote`]s
140    async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
141}
142
143/// Mint Proof Transaction trait
144#[async_trait]
145pub trait ProofsTransaction<'a> {
146    /// Mint Proof Database Error
147    type Err: Into<Error> + From<Error>;
148
149    /// Add  [`Proofs`]
150    ///
151    /// Adds proofs to the database. The database should error if the proof already exits, with a
152    /// `AttemptUpdateSpentProof` if the proof is already spent or a `Duplicate` error otherwise.
153    async fn add_proofs(&mut self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
154    /// Updates the proofs to a given states and return the previous states
155    async fn update_proofs_states(
156        &mut self,
157        ys: &[PublicKey],
158        proofs_state: State,
159    ) -> Result<Vec<Option<State>>, Self::Err>;
160
161    /// Remove [`Proofs`]
162    async fn remove_proofs(
163        &mut self,
164        ys: &[PublicKey],
165        quote_id: Option<Uuid>,
166    ) -> Result<(), Self::Err>;
167}
168
169/// Mint Proof Database trait
170#[async_trait]
171pub trait ProofsDatabase {
172    /// Mint Proof Database Error
173    type Err: Into<Error> + From<Error>;
174
175    /// Get [`Proofs`] by ys
176    async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
177    /// Get ys by quote id
178    async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err>;
179    /// Get [`Proofs`] state
180    async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
181    /// Get [`Proofs`] by state
182    async fn get_proofs_by_keyset_id(
183        &self,
184        keyset_id: &Id,
185    ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
186}
187
188#[async_trait]
189/// Mint Signatures Transaction trait
190pub trait SignaturesTransaction<'a> {
191    /// Mint Signature Database Error
192    type Err: Into<Error> + From<Error>;
193
194    /// Add [`BlindSignature`]
195    async fn add_blind_signatures(
196        &mut self,
197        blinded_messages: &[PublicKey],
198        blind_signatures: &[BlindSignature],
199        quote_id: Option<Uuid>,
200    ) -> Result<(), Self::Err>;
201
202    /// Get [`BlindSignature`]s
203    async fn get_blind_signatures(
204        &mut self,
205        blinded_messages: &[PublicKey],
206    ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
207}
208
209#[async_trait]
210/// Mint Signatures Database trait
211pub trait SignaturesDatabase {
212    /// Mint Signature Database Error
213    type Err: Into<Error> + From<Error>;
214
215    /// Get [`BlindSignature`]s
216    async fn get_blind_signatures(
217        &self,
218        blinded_messages: &[PublicKey],
219    ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
220    /// Get [`BlindSignature`]s for keyset_id
221    async fn get_blind_signatures_for_keyset(
222        &self,
223        keyset_id: &Id,
224    ) -> Result<Vec<BlindSignature>, Self::Err>;
225    /// Get [`BlindSignature`]s for quote
226    async fn get_blind_signatures_for_quote(
227        &self,
228        quote_id: &Uuid,
229    ) -> Result<Vec<BlindSignature>, Self::Err>;
230}
231
232#[async_trait]
233/// Commit and Rollback
234pub trait DbTransactionFinalizer {
235    /// Mint Signature Database Error
236    type Err: Into<Error> + From<Error>;
237
238    /// Commits all the changes into the database
239    async fn commit(self: Box<Self>) -> Result<(), Self::Err>;
240
241    /// Rollbacks the write transaction
242    async fn rollback(self: Box<Self>) -> Result<(), Self::Err>;
243}
244
245/// Base database writer
246#[async_trait]
247pub trait Transaction<'a, Error>:
248    DbTransactionFinalizer<Err = Error>
249    + QuotesTransaction<'a, Err = Error>
250    + SignaturesTransaction<'a, Err = Error>
251    + ProofsTransaction<'a, Err = Error>
252{
253    /// Set [`QuoteTTL`]
254    async fn set_quote_ttl(&mut self, quote_ttl: QuoteTTL) -> Result<(), Error>;
255
256    /// Set [`MintInfo`]
257    async fn set_mint_info(&mut self, mint_info: MintInfo) -> Result<(), Error>;
258}
259
260/// Mint Database trait
261#[async_trait]
262pub trait Database<Error>:
263    QuotesDatabase<Err = Error> + ProofsDatabase<Err = Error> + SignaturesDatabase<Err = Error>
264{
265    /// Beings a transaction
266    async fn begin_transaction<'a>(
267        &'a self,
268    ) -> Result<Box<dyn Transaction<'a, Error> + Send + Sync + 'a>, Error>;
269
270    /// Get [`MintInfo`]
271    async fn get_mint_info(&self) -> Result<MintInfo, Error>;
272
273    /// Get [`QuoteTTL`]
274    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Error>;
275}