Skip to main content

cdk_common/database/
mod.rs

1//! CDK Database
2
3mod kvstore;
4
5#[cfg(feature = "mint")]
6pub mod mint;
7#[cfg(feature = "wallet")]
8pub mod wallet;
9
10// Re-export shared KVStore types at the top level for both mint and wallet
11pub use kvstore::{
12    validate_kvstore_params, validate_kvstore_string, KVStore, KVStoreCompareAndSwap,
13    KVStoreDatabase, KVStoreTransaction, KVSTORE_NAMESPACE_KEY_ALPHABET,
14    KVSTORE_NAMESPACE_KEY_MAX_LEN,
15};
16
17/// Arc-wrapped KV store for shared ownership
18pub type DynKVStore = std::sync::Arc<dyn KVStore<Err = Error> + Send + Sync>;
19
20#[cfg(feature = "mint")]
21pub use mint::{
22    Database as MintDatabase, DynMintDatabase, DynMintTransaction,
23    KeysDatabase as MintKeysDatabase, KeysDatabaseTransaction as MintKeyDatabaseTransaction,
24    ProofsDatabase as MintProofsDatabase, ProofsTransaction as MintProofsTransaction,
25    QuotesDatabase as MintQuotesDatabase, QuotesTransaction as MintQuotesTransaction,
26    SignaturesDatabase as MintSignaturesDatabase,
27    SignaturesTransaction as MintSignatureTransaction, Transaction as MintTransaction,
28};
29#[cfg(feature = "mint")]
30pub use mint::{DynMintAuthDatabase, MintAuthDatabase, MintAuthTransaction};
31#[cfg(feature = "wallet")]
32pub use wallet::Database as WalletDatabase;
33
34/// Data conversion error
35#[derive(thiserror::Error, Debug)]
36pub enum ConversionError {
37    /// Missing columns
38    #[error("Not enough elements: expected {0}, got {1}")]
39    MissingColumn(usize, usize),
40
41    /// Missing parameter
42    #[error("Missing parameter {0}")]
43    MissingParameter(String),
44
45    /// Invalid db type
46    #[error("Invalid type from db, expected {0} got {1}")]
47    InvalidType(String, String),
48
49    /// Invalid data conversion in column
50    #[error("Error converting {1}, expecting type {0}")]
51    InvalidConversion(String, String),
52
53    /// Mint Url Error
54    #[error(transparent)]
55    MintUrl(#[from] crate::mint_url::Error),
56
57    /// NUT00 Error
58    #[error(transparent)]
59    CDKNUT00(#[from] crate::nuts::nut00::Error),
60
61    /// NUT01 Error
62    #[error(transparent)]
63    CDKNUT01(#[from] crate::nuts::nut01::Error),
64
65    /// NUT02 Error
66    #[error(transparent)]
67    CDKNUT02(#[from] crate::nuts::nut02::Error),
68
69    /// NUT04 Error
70    #[error(transparent)]
71    CDKNUT04(#[from] crate::nuts::nut04::Error),
72
73    /// NUT05 Error
74    #[error(transparent)]
75    CDKNUT05(#[from] crate::nuts::nut05::Error),
76
77    /// NUT07 Error
78    #[error(transparent)]
79    CDKNUT07(#[from] crate::nuts::nut07::Error),
80
81    /// NUT23 Error
82    #[error(transparent)]
83    CDKNUT23(#[from] crate::nuts::nut23::Error),
84
85    /// Secret Error
86    #[error(transparent)]
87    CDKSECRET(#[from] crate::secret::Error),
88
89    /// Serde Error
90    #[error(transparent)]
91    Serde(#[from] serde_json::Error),
92
93    /// BIP32 Error
94    #[error(transparent)]
95    BIP32(#[from] bitcoin::bip32::Error),
96
97    /// Generic error
98    #[error(transparent)]
99    Generic(#[from] Box<crate::Error>),
100}
101
102impl From<crate::Error> for ConversionError {
103    fn from(err: crate::Error) -> Self {
104        ConversionError::Generic(Box::new(err))
105    }
106}
107
108/// CDK_database error
109#[derive(Debug, thiserror::Error)]
110pub enum Error {
111    /// Database Error
112    #[error(transparent)]
113    Database(Box<dyn std::error::Error + Send + Sync>),
114
115    /// Duplicate entry
116    #[error("Duplicate entry")]
117    Duplicate,
118
119    /// Locked resource
120    #[error("Locked resource")]
121    Locked,
122
123    /// Amount overflow
124    #[error("Amount overflow")]
125    AmountOverflow,
126    /// Amount zero
127    #[error("Amount zero")]
128    AmountZero,
129
130    /// DHKE error
131    #[error(transparent)]
132    DHKE(#[from] crate::dhke::Error),
133    /// NUT00 Error
134    #[error(transparent)]
135    NUT00(#[from] crate::nuts::nut00::Error),
136    /// NUT01 Error
137    #[error(transparent)]
138    NUT01(#[from] crate::nuts::nut01::Error),
139    /// NUT02 Error
140    #[error(transparent)]
141    NUT02(#[from] crate::nuts::nut02::Error),
142    /// NUT22 Error
143    #[error(transparent)]
144    NUT22(#[from] crate::nuts::nut22::Error),
145    /// NUT04 Error
146    #[error(transparent)]
147    NUT04(#[from] crate::nuts::nut04::Error),
148    /// Quote ID Error
149    #[error(transparent)]
150    #[cfg(feature = "mint")]
151    QuoteId(#[from] crate::quote_id::QuoteIdError),
152    /// Serde Error
153    #[error(transparent)]
154    Serde(#[from] serde_json::Error),
155    /// Unknown Quote
156    #[error("Unknown Quote")]
157    UnknownQuote,
158    /// Attempt to remove spent proof
159    #[error("Attempt to remove spent proof")]
160    AttemptRemoveSpentProof,
161    /// Attempt to update state of spent proof
162    #[error("Attempt to update state of spent proof")]
163    AttemptUpdateSpentProof,
164    /// Proof not found
165    #[error("Proof not found")]
166    ProofNotFound,
167    /// Proof not in unspent state (may be reserved, pending, or spent)
168    #[error("Proof not in unspent state")]
169    ProofNotUnspent,
170    /// Quote is already in use by another operation
171    #[error("Quote already in use by another operation")]
172    QuoteAlreadyInUse,
173    /// Invalid keyset
174    #[error("Unknown or invalid keyset")]
175    InvalidKeysetId,
176    #[cfg(feature = "mint")]
177    /// Invalid state transition
178    #[error("Invalid state transition")]
179    InvalidStateTransition(crate::state::Error),
180
181    /// Invalid connection settings
182    #[error("Invalid credentials {0}")]
183    InvalidConnectionSettings(String),
184
185    /// Unexpected database response
186    #[error("Invalid database response")]
187    InvalidDbResponse,
188
189    /// Internal error
190    #[error("Internal {0}")]
191    Internal(String),
192
193    /// Data conversion error
194    #[error(transparent)]
195    Conversion(#[from] ConversionError),
196
197    /// Missing Placeholder value
198    #[error("Missing placeholder value {0}")]
199    MissingPlaceholder(String),
200
201    /// Empty IN clause
202    #[error("Empty IN clause for placeholder: {0}")]
203    EmptyInClause(String),
204
205    /// Unknown quote ttl
206    #[error("Unknown quote ttl")]
207    UnknownQuoteTTL,
208
209    /// Invalid UUID
210    #[error("Invalid UUID: {0}")]
211    InvalidUuid(String),
212
213    /// QuoteNotFound
214    #[error("Quote not found")]
215    QuoteNotFound,
216
217    /// KV Store invalid key or namespace
218    #[error("Invalid KV store key or namespace: {0}")]
219    KVStoreInvalidKey(String),
220
221    /// Concurrent update detected
222    #[error("Concurrent update detected")]
223    ConcurrentUpdate,
224}
225
226#[cfg(feature = "mint")]
227impl From<crate::state::Error> for Error {
228    fn from(state: crate::state::Error) -> Self {
229        match state {
230            crate::state::Error::AlreadySpent => Error::AttemptUpdateSpentProof,
231            _ => Error::InvalidStateTransition(state),
232        }
233    }
234}
235
236#[async_trait::async_trait]
237/// Commit and Rollback
238pub trait DbTransactionFinalizer {
239    /// Mint Signature Database Error
240    type Err: Into<Error> + From<Error>;
241
242    /// Commits all the changes into the database
243    async fn commit(self: Box<Self>) -> Result<(), Self::Err>;
244
245    /// Rollbacks the write transaction
246    async fn rollback(self: Box<Self>) -> Result<(), Self::Err>;
247}