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