mod.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. //! CDK Database
  2. use std::collections::HashMap;
  3. use async_trait::async_trait;
  4. use cashu::quote_id::QuoteId;
  5. use cashu::Amount;
  6. use super::{DbTransactionFinalizer, Error};
  7. use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote, Operation};
  8. use crate::nuts::{
  9. BlindSignature, BlindedMessage, CurrencyUnit, Id, MeltQuoteState, Proof, Proofs, PublicKey,
  10. State,
  11. };
  12. use crate::payment::PaymentIdentifier;
  13. #[cfg(feature = "auth")]
  14. mod auth;
  15. #[cfg(feature = "test")]
  16. pub mod test;
  17. #[cfg(feature = "auth")]
  18. pub use auth::{DynMintAuthDatabase, MintAuthDatabase, MintAuthTransaction};
  19. // Re-export KVStore types from shared module for backward compatibility
  20. pub use super::kvstore::{
  21. validate_kvstore_params, validate_kvstore_string, KVStore, KVStoreDatabase, KVStoreTransaction,
  22. KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN,
  23. };
  24. /// Information about a melt request stored in the database
  25. #[derive(Debug, Clone, PartialEq, Eq)]
  26. pub struct MeltRequestInfo {
  27. /// Total amount of all input proofs in the melt request
  28. pub inputs_amount: Amount,
  29. /// Fee amount associated with the input proofs
  30. pub inputs_fee: Amount,
  31. /// Blinded messages for change outputs
  32. pub change_outputs: Vec<BlindedMessage>,
  33. }
  34. /// KeysDatabaseWriter
  35. #[async_trait]
  36. pub trait KeysDatabaseTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
  37. /// Add Active Keyset
  38. async fn set_active_keyset(&mut self, unit: CurrencyUnit, id: Id) -> Result<(), Error>;
  39. /// Add [`MintKeySetInfo`]
  40. async fn add_keyset_info(&mut self, keyset: MintKeySetInfo) -> Result<(), Error>;
  41. }
  42. /// Mint Keys Database trait
  43. #[async_trait]
  44. pub trait KeysDatabase {
  45. /// Mint Keys Database Error
  46. type Err: Into<Error> + From<Error>;
  47. /// Begins a transaction
  48. async fn begin_transaction<'a>(
  49. &'a self,
  50. ) -> Result<Box<dyn KeysDatabaseTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
  51. /// Get Active Keyset
  52. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>;
  53. /// Get all Active Keyset
  54. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err>;
  55. /// Get [`MintKeySetInfo`]
  56. async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>;
  57. /// Get [`MintKeySetInfo`]s
  58. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
  59. }
  60. /// Mint Quote Database writer trait
  61. #[async_trait]
  62. pub trait QuotesTransaction {
  63. /// Mint Quotes Database Error
  64. type Err: Into<Error> + From<Error>;
  65. /// Add melt_request with quote_id, inputs_amount, and inputs_fee
  66. async fn add_melt_request(
  67. &mut self,
  68. quote_id: &QuoteId,
  69. inputs_amount: Amount,
  70. inputs_fee: Amount,
  71. ) -> Result<(), Self::Err>;
  72. /// Add blinded_messages for a quote_id
  73. async fn add_blinded_messages(
  74. &mut self,
  75. quote_id: Option<&QuoteId>,
  76. blinded_messages: &[BlindedMessage],
  77. operation: &Operation,
  78. ) -> Result<(), Self::Err>;
  79. /// Delete blinded_messages by their blinded secrets
  80. async fn delete_blinded_messages(
  81. &mut self,
  82. blinded_secrets: &[PublicKey],
  83. ) -> Result<(), Self::Err>;
  84. /// Get melt_request and associated blinded_messages by quote_id
  85. async fn get_melt_request_and_blinded_messages(
  86. &mut self,
  87. quote_id: &QuoteId,
  88. ) -> Result<Option<MeltRequestInfo>, Self::Err>;
  89. /// Delete melt_request and associated blinded_messages by quote_id
  90. async fn delete_melt_request(&mut self, quote_id: &QuoteId) -> Result<(), Self::Err>;
  91. /// Get [`MintMintQuote`] and lock it for update in this transaction
  92. async fn get_mint_quote(
  93. &mut self,
  94. quote_id: &QuoteId,
  95. ) -> Result<Option<MintMintQuote>, Self::Err>;
  96. /// Add [`MintMintQuote`]
  97. async fn add_mint_quote(&mut self, quote: MintMintQuote) -> Result<(), Self::Err>;
  98. /// Increment amount paid [`MintMintQuote`]
  99. async fn increment_mint_quote_amount_paid(
  100. &mut self,
  101. quote_id: &QuoteId,
  102. amount_paid: Amount,
  103. payment_id: String,
  104. ) -> Result<Amount, Self::Err>;
  105. /// Increment amount paid [`MintMintQuote`]
  106. async fn increment_mint_quote_amount_issued(
  107. &mut self,
  108. quote_id: &QuoteId,
  109. amount_issued: Amount,
  110. ) -> Result<Amount, Self::Err>;
  111. /// Get [`mint::MeltQuote`] and lock it for update in this transaction
  112. async fn get_melt_quote(
  113. &mut self,
  114. quote_id: &QuoteId,
  115. ) -> Result<Option<mint::MeltQuote>, Self::Err>;
  116. /// Add [`mint::MeltQuote`]
  117. async fn add_melt_quote(&mut self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
  118. /// Updates the request lookup id for a melt quote
  119. async fn update_melt_quote_request_lookup_id(
  120. &mut self,
  121. quote_id: &QuoteId,
  122. new_request_lookup_id: &PaymentIdentifier,
  123. ) -> Result<(), Self::Err>;
  124. /// Update [`mint::MeltQuote`] state
  125. ///
  126. /// It is expected for this function to fail if the state is already set to the new state
  127. async fn update_melt_quote_state(
  128. &mut self,
  129. quote_id: &QuoteId,
  130. new_state: MeltQuoteState,
  131. payment_proof: Option<String>,
  132. ) -> Result<(MeltQuoteState, mint::MeltQuote), Self::Err>;
  133. /// Get all [`MintMintQuote`]s and lock it for update in this transaction
  134. async fn get_mint_quote_by_request(
  135. &mut self,
  136. request: &str,
  137. ) -> Result<Option<MintMintQuote>, Self::Err>;
  138. /// Get all [`MintMintQuote`]s
  139. async fn get_mint_quote_by_request_lookup_id(
  140. &mut self,
  141. request_lookup_id: &PaymentIdentifier,
  142. ) -> Result<Option<MintMintQuote>, Self::Err>;
  143. }
  144. /// Mint Quote Database trait
  145. #[async_trait]
  146. pub trait QuotesDatabase {
  147. /// Mint Quotes Database Error
  148. type Err: Into<Error> + From<Error>;
  149. /// Get [`MintMintQuote`]
  150. async fn get_mint_quote(&self, quote_id: &QuoteId) -> Result<Option<MintMintQuote>, Self::Err>;
  151. /// Get all [`MintMintQuote`]s
  152. async fn get_mint_quote_by_request(
  153. &self,
  154. request: &str,
  155. ) -> Result<Option<MintMintQuote>, Self::Err>;
  156. /// Get all [`MintMintQuote`]s
  157. async fn get_mint_quote_by_request_lookup_id(
  158. &self,
  159. request_lookup_id: &PaymentIdentifier,
  160. ) -> Result<Option<MintMintQuote>, Self::Err>;
  161. /// Get Mint Quotes
  162. async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
  163. /// Get [`mint::MeltQuote`]
  164. async fn get_melt_quote(
  165. &self,
  166. quote_id: &QuoteId,
  167. ) -> Result<Option<mint::MeltQuote>, Self::Err>;
  168. /// Get all [`mint::MeltQuote`]s
  169. async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
  170. }
  171. /// Mint Proof Transaction trait
  172. #[async_trait]
  173. pub trait ProofsTransaction {
  174. /// Mint Proof Database Error
  175. type Err: Into<Error> + From<Error>;
  176. /// Add [`Proofs`]
  177. ///
  178. /// Adds proofs to the database. The database should error if the proof already exits, with a
  179. /// `AttemptUpdateSpentProof` if the proof is already spent or a `Duplicate` error otherwise.
  180. async fn add_proofs(
  181. &mut self,
  182. proof: Proofs,
  183. quote_id: Option<QuoteId>,
  184. operation: &Operation,
  185. ) -> Result<(), Self::Err>;
  186. /// Updates the proofs to a given states and return the previous states
  187. async fn update_proofs_states(
  188. &mut self,
  189. ys: &[PublicKey],
  190. proofs_state: State,
  191. ) -> Result<Vec<Option<State>>, Self::Err>;
  192. /// Remove [`Proofs`]
  193. async fn remove_proofs(
  194. &mut self,
  195. ys: &[PublicKey],
  196. quote_id: Option<QuoteId>,
  197. ) -> Result<(), Self::Err>;
  198. /// Get ys by quote id
  199. async fn get_proof_ys_by_quote_id(
  200. &self,
  201. quote_id: &QuoteId,
  202. ) -> Result<Vec<PublicKey>, Self::Err>;
  203. /// Get proof ys by operation id
  204. async fn get_proof_ys_by_operation_id(
  205. &self,
  206. operation_id: &uuid::Uuid,
  207. ) -> Result<Vec<PublicKey>, Self::Err>;
  208. }
  209. /// Mint Proof Database trait
  210. #[async_trait]
  211. pub trait ProofsDatabase {
  212. /// Mint Proof Database Error
  213. type Err: Into<Error> + From<Error>;
  214. /// Get [`Proofs`] by ys
  215. async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
  216. /// Get ys by quote id
  217. async fn get_proof_ys_by_quote_id(
  218. &self,
  219. quote_id: &QuoteId,
  220. ) -> Result<Vec<PublicKey>, Self::Err>;
  221. /// Get [`Proofs`] state
  222. async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
  223. /// Get [`Proofs`] by state
  224. async fn get_proofs_by_keyset_id(
  225. &self,
  226. keyset_id: &Id,
  227. ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
  228. /// Get total proofs redeemed by keyset id
  229. async fn get_total_redeemed(&self) -> Result<HashMap<Id, Amount>, Self::Err>;
  230. /// Get proof ys by operation id
  231. async fn get_proof_ys_by_operation_id(
  232. &self,
  233. operation_id: &uuid::Uuid,
  234. ) -> Result<Vec<PublicKey>, Self::Err>;
  235. }
  236. #[async_trait]
  237. /// Mint Signatures Transaction trait
  238. pub trait SignaturesTransaction {
  239. /// Mint Signature Database Error
  240. type Err: Into<Error> + From<Error>;
  241. /// Add [`BlindSignature`]
  242. async fn add_blind_signatures(
  243. &mut self,
  244. blinded_messages: &[PublicKey],
  245. blind_signatures: &[BlindSignature],
  246. quote_id: Option<QuoteId>,
  247. ) -> Result<(), Self::Err>;
  248. /// Get [`BlindSignature`]s
  249. async fn get_blind_signatures(
  250. &mut self,
  251. blinded_messages: &[PublicKey],
  252. ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
  253. }
  254. #[async_trait]
  255. /// Mint Signatures Database trait
  256. pub trait SignaturesDatabase {
  257. /// Mint Signature Database Error
  258. type Err: Into<Error> + From<Error>;
  259. /// Get [`BlindSignature`]s
  260. async fn get_blind_signatures(
  261. &self,
  262. blinded_messages: &[PublicKey],
  263. ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
  264. /// Get [`BlindSignature`]s for keyset_id
  265. async fn get_blind_signatures_for_keyset(
  266. &self,
  267. keyset_id: &Id,
  268. ) -> Result<Vec<BlindSignature>, Self::Err>;
  269. /// Get [`BlindSignature`]s for quote
  270. async fn get_blind_signatures_for_quote(
  271. &self,
  272. quote_id: &QuoteId,
  273. ) -> Result<Vec<BlindSignature>, Self::Err>;
  274. /// Get total amount issued by keyset id
  275. async fn get_total_issued(&self) -> Result<HashMap<Id, Amount>, Self::Err>;
  276. /// Get blinded secrets (B values) by operation id
  277. async fn get_blinded_secrets_by_operation_id(
  278. &self,
  279. operation_id: &uuid::Uuid,
  280. ) -> Result<Vec<PublicKey>, Self::Err>;
  281. }
  282. #[async_trait]
  283. /// Saga Transaction trait
  284. pub trait SagaTransaction {
  285. /// Saga Database Error
  286. type Err: Into<Error> + From<Error>;
  287. /// Get saga by operation_id
  288. async fn get_saga(
  289. &mut self,
  290. operation_id: &uuid::Uuid,
  291. ) -> Result<Option<mint::Saga>, Self::Err>;
  292. /// Add saga
  293. async fn add_saga(&mut self, saga: &mint::Saga) -> Result<(), Self::Err>;
  294. /// Update saga state (only updates state and updated_at fields)
  295. async fn update_saga(
  296. &mut self,
  297. operation_id: &uuid::Uuid,
  298. new_state: mint::SagaStateEnum,
  299. ) -> Result<(), Self::Err>;
  300. /// Delete saga
  301. async fn delete_saga(&mut self, operation_id: &uuid::Uuid) -> Result<(), Self::Err>;
  302. }
  303. #[async_trait]
  304. /// Saga Database trait
  305. pub trait SagaDatabase {
  306. /// Saga Database Error
  307. type Err: Into<Error> + From<Error>;
  308. /// Get all incomplete sagas for a given operation kind
  309. async fn get_incomplete_sagas(
  310. &self,
  311. operation_kind: mint::OperationKind,
  312. ) -> Result<Vec<mint::Saga>, Self::Err>;
  313. }
  314. #[async_trait]
  315. /// Completed Operations Transaction trait
  316. pub trait CompletedOperationsTransaction {
  317. /// Completed Operations Database Error
  318. type Err: Into<Error> + From<Error>;
  319. /// Add completed operation
  320. async fn add_completed_operation(
  321. &mut self,
  322. operation: &mint::Operation,
  323. fee_by_keyset: &std::collections::HashMap<crate::nuts::Id, crate::Amount>,
  324. ) -> Result<(), Self::Err>;
  325. }
  326. #[async_trait]
  327. /// Completed Operations Database trait
  328. pub trait CompletedOperationsDatabase {
  329. /// Completed Operations Database Error
  330. type Err: Into<Error> + From<Error>;
  331. /// Get completed operation by operation_id
  332. async fn get_completed_operation(
  333. &self,
  334. operation_id: &uuid::Uuid,
  335. ) -> Result<Option<mint::Operation>, Self::Err>;
  336. /// Get completed operations by operation kind
  337. async fn get_completed_operations_by_kind(
  338. &self,
  339. operation_kind: mint::OperationKind,
  340. ) -> Result<Vec<mint::Operation>, Self::Err>;
  341. /// Get all completed operations
  342. async fn get_completed_operations(&self) -> Result<Vec<mint::Operation>, Self::Err>;
  343. }
  344. /// Base database writer
  345. pub trait Transaction<Error>:
  346. DbTransactionFinalizer<Err = Error>
  347. + QuotesTransaction<Err = Error>
  348. + SignaturesTransaction<Err = Error>
  349. + ProofsTransaction<Err = Error>
  350. + KVStoreTransaction<Error>
  351. + SagaTransaction<Err = Error>
  352. + CompletedOperationsTransaction<Err = Error>
  353. {
  354. }
  355. /// Mint Database trait
  356. #[async_trait]
  357. pub trait Database<Error>:
  358. KVStoreDatabase<Err = Error>
  359. + QuotesDatabase<Err = Error>
  360. + ProofsDatabase<Err = Error>
  361. + SignaturesDatabase<Err = Error>
  362. + SagaDatabase<Err = Error>
  363. + CompletedOperationsDatabase<Err = Error>
  364. {
  365. /// Begins a transaction
  366. async fn begin_transaction(&self) -> Result<Box<dyn Transaction<Error> + Send + Sync>, Error>;
  367. }
  368. /// Type alias for Mint Database
  369. pub type DynMintDatabase = std::sync::Arc<dyn Database<Error> + Send + Sync>;