mod.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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::Error;
  7. use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote};
  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. /// Valid ASCII characters for namespace and key strings in KV store
  20. pub const KVSTORE_NAMESPACE_KEY_ALPHABET: &str =
  21. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  22. /// Maximum length for namespace and key strings in KV store
  23. pub const KVSTORE_NAMESPACE_KEY_MAX_LEN: usize = 120;
  24. /// Validates that a string contains only valid KV store characters and is within length limits
  25. pub fn validate_kvstore_string(s: &str) -> Result<(), Error> {
  26. if s.len() > KVSTORE_NAMESPACE_KEY_MAX_LEN {
  27. return Err(Error::KVStoreInvalidKey(format!(
  28. "{KVSTORE_NAMESPACE_KEY_MAX_LEN} exceeds maximum length of key characters"
  29. )));
  30. }
  31. if !s
  32. .chars()
  33. .all(|c| KVSTORE_NAMESPACE_KEY_ALPHABET.contains(c))
  34. {
  35. return Err(Error::KVStoreInvalidKey("key contains invalid characters. Only ASCII letters, numbers, underscore, and hyphen are allowed".to_string()));
  36. }
  37. Ok(())
  38. }
  39. /// Validates namespace and key parameters for KV store operations
  40. pub fn validate_kvstore_params(
  41. primary_namespace: &str,
  42. secondary_namespace: &str,
  43. key: &str,
  44. ) -> Result<(), Error> {
  45. // Validate primary namespace
  46. validate_kvstore_string(primary_namespace)?;
  47. // Validate secondary namespace
  48. validate_kvstore_string(secondary_namespace)?;
  49. // Validate key
  50. validate_kvstore_string(key)?;
  51. // Check empty namespace rules
  52. if primary_namespace.is_empty() && !secondary_namespace.is_empty() {
  53. return Err(Error::KVStoreInvalidKey(
  54. "If primary_namespace is empty, secondary_namespace must also be empty".to_string(),
  55. ));
  56. }
  57. // Check for potential collisions between keys and namespaces in the same namespace
  58. let namespace_key = format!("{primary_namespace}/{secondary_namespace}");
  59. if key == primary_namespace || key == secondary_namespace || key == namespace_key {
  60. return Err(Error::KVStoreInvalidKey(format!(
  61. "Key '{key}' conflicts with namespace names"
  62. )));
  63. }
  64. Ok(())
  65. }
  66. /// Information about a melt request stored in the database
  67. #[derive(Debug, Clone, PartialEq, Eq)]
  68. pub struct MeltRequestInfo {
  69. /// Total amount of all input proofs in the melt request
  70. pub inputs_amount: Amount,
  71. /// Fee amount associated with the input proofs
  72. pub inputs_fee: Amount,
  73. /// Blinded messages for change outputs
  74. pub change_outputs: Vec<BlindedMessage>,
  75. }
  76. /// KeysDatabaseWriter
  77. #[async_trait]
  78. pub trait KeysDatabaseTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
  79. /// Add Active Keyset
  80. async fn set_active_keyset(&mut self, unit: CurrencyUnit, id: Id) -> Result<(), Error>;
  81. /// Add [`MintKeySetInfo`]
  82. async fn add_keyset_info(&mut self, keyset: MintKeySetInfo) -> Result<(), Error>;
  83. }
  84. /// Mint Keys Database trait
  85. #[async_trait]
  86. pub trait KeysDatabase {
  87. /// Mint Keys Database Error
  88. type Err: Into<Error> + From<Error>;
  89. /// Beings a transaction
  90. async fn begin_transaction<'a>(
  91. &'a self,
  92. ) -> Result<Box<dyn KeysDatabaseTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
  93. /// Get Active Keyset
  94. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>;
  95. /// Get all Active Keyset
  96. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err>;
  97. /// Get [`MintKeySetInfo`]
  98. async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>;
  99. /// Get [`MintKeySetInfo`]s
  100. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
  101. }
  102. /// Mint Quote Database writer trait
  103. #[async_trait]
  104. pub trait QuotesTransaction<'a> {
  105. /// Mint Quotes Database Error
  106. type Err: Into<Error> + From<Error>;
  107. /// Add melt_request with quote_id, inputs_amount, and inputs_fee
  108. async fn add_melt_request(
  109. &mut self,
  110. quote_id: &QuoteId,
  111. inputs_amount: Amount,
  112. inputs_fee: Amount,
  113. ) -> Result<(), Self::Err>;
  114. /// Add blinded_messages for a quote_id
  115. async fn add_blinded_messages(
  116. &mut self,
  117. quote_id: Option<&QuoteId>,
  118. blinded_messages: &[BlindedMessage],
  119. ) -> Result<(), Self::Err>;
  120. /// Delete blinded_messages by their blinded secrets
  121. async fn delete_blinded_messages(
  122. &mut self,
  123. blinded_secrets: &[PublicKey],
  124. ) -> Result<(), Self::Err>;
  125. /// Get melt_request and associated blinded_messages by quote_id
  126. async fn get_melt_request_and_blinded_messages(
  127. &mut self,
  128. quote_id: &QuoteId,
  129. ) -> Result<Option<MeltRequestInfo>, Self::Err>;
  130. /// Delete melt_request and associated blinded_messages by quote_id
  131. async fn delete_melt_request(&mut self, quote_id: &QuoteId) -> Result<(), Self::Err>;
  132. /// Get [`MintMintQuote`] and lock it for update in this transaction
  133. async fn get_mint_quote(
  134. &mut self,
  135. quote_id: &QuoteId,
  136. ) -> Result<Option<MintMintQuote>, Self::Err>;
  137. /// Add [`MintMintQuote`]
  138. async fn add_mint_quote(&mut self, quote: MintMintQuote) -> Result<(), Self::Err>;
  139. /// Increment amount paid [`MintMintQuote`]
  140. async fn increment_mint_quote_amount_paid(
  141. &mut self,
  142. quote_id: &QuoteId,
  143. amount_paid: Amount,
  144. payment_id: String,
  145. ) -> Result<Amount, Self::Err>;
  146. /// Increment amount paid [`MintMintQuote`]
  147. async fn increment_mint_quote_amount_issued(
  148. &mut self,
  149. quote_id: &QuoteId,
  150. amount_issued: Amount,
  151. ) -> Result<Amount, Self::Err>;
  152. /// Get [`mint::MeltQuote`] and lock it for update in this transaction
  153. async fn get_melt_quote(
  154. &mut self,
  155. quote_id: &QuoteId,
  156. ) -> Result<Option<mint::MeltQuote>, Self::Err>;
  157. /// Add [`mint::MeltQuote`]
  158. async fn add_melt_quote(&mut self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
  159. /// Updates the request lookup id for a melt quote
  160. async fn update_melt_quote_request_lookup_id(
  161. &mut self,
  162. quote_id: &QuoteId,
  163. new_request_lookup_id: &PaymentIdentifier,
  164. ) -> Result<(), Self::Err>;
  165. /// Update [`mint::MeltQuote`] state
  166. ///
  167. /// It is expected for this function to fail if the state is already set to the new state
  168. async fn update_melt_quote_state(
  169. &mut self,
  170. quote_id: &QuoteId,
  171. new_state: MeltQuoteState,
  172. payment_proof: Option<String>,
  173. ) -> Result<(MeltQuoteState, mint::MeltQuote), Self::Err>;
  174. /// Get all [`MintMintQuote`]s and lock it for update in this transaction
  175. async fn get_mint_quote_by_request(
  176. &mut self,
  177. request: &str,
  178. ) -> Result<Option<MintMintQuote>, Self::Err>;
  179. /// Get all [`MintMintQuote`]s
  180. async fn get_mint_quote_by_request_lookup_id(
  181. &mut self,
  182. request_lookup_id: &PaymentIdentifier,
  183. ) -> Result<Option<MintMintQuote>, Self::Err>;
  184. }
  185. /// Mint Quote Database trait
  186. #[async_trait]
  187. pub trait QuotesDatabase {
  188. /// Mint Quotes Database Error
  189. type Err: Into<Error> + From<Error>;
  190. /// Get [`MintMintQuote`]
  191. async fn get_mint_quote(&self, quote_id: &QuoteId) -> Result<Option<MintMintQuote>, Self::Err>;
  192. /// Get all [`MintMintQuote`]s
  193. async fn get_mint_quote_by_request(
  194. &self,
  195. request: &str,
  196. ) -> Result<Option<MintMintQuote>, Self::Err>;
  197. /// Get all [`MintMintQuote`]s
  198. async fn get_mint_quote_by_request_lookup_id(
  199. &self,
  200. request_lookup_id: &PaymentIdentifier,
  201. ) -> Result<Option<MintMintQuote>, Self::Err>;
  202. /// Get Mint Quotes
  203. async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
  204. /// Get [`mint::MeltQuote`]
  205. async fn get_melt_quote(
  206. &self,
  207. quote_id: &QuoteId,
  208. ) -> Result<Option<mint::MeltQuote>, Self::Err>;
  209. /// Get all [`mint::MeltQuote`]s
  210. async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
  211. }
  212. /// Mint Proof Transaction trait
  213. #[async_trait]
  214. pub trait ProofsTransaction<'a> {
  215. /// Mint Proof Database Error
  216. type Err: Into<Error> + From<Error>;
  217. /// Add [`Proofs`]
  218. ///
  219. /// Adds proofs to the database. The database should error if the proof already exits, with a
  220. /// `AttemptUpdateSpentProof` if the proof is already spent or a `Duplicate` error otherwise.
  221. async fn add_proofs(
  222. &mut self,
  223. proof: Proofs,
  224. quote_id: Option<QuoteId>,
  225. ) -> Result<(), Self::Err>;
  226. /// Updates the proofs to a given states and return the previous states
  227. async fn update_proofs_states(
  228. &mut self,
  229. ys: &[PublicKey],
  230. proofs_state: State,
  231. ) -> Result<Vec<Option<State>>, Self::Err>;
  232. /// Remove [`Proofs`]
  233. async fn remove_proofs(
  234. &mut self,
  235. ys: &[PublicKey],
  236. quote_id: Option<QuoteId>,
  237. ) -> Result<(), Self::Err>;
  238. /// Get ys by quote id
  239. async fn get_proof_ys_by_quote_id(
  240. &self,
  241. quote_id: &QuoteId,
  242. ) -> Result<Vec<PublicKey>, Self::Err>;
  243. }
  244. /// Mint Proof Database trait
  245. #[async_trait]
  246. pub trait ProofsDatabase {
  247. /// Mint Proof Database Error
  248. type Err: Into<Error> + From<Error>;
  249. /// Get [`Proofs`] by ys
  250. async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
  251. /// Get ys by quote id
  252. async fn get_proof_ys_by_quote_id(
  253. &self,
  254. quote_id: &QuoteId,
  255. ) -> Result<Vec<PublicKey>, Self::Err>;
  256. /// Get [`Proofs`] state
  257. async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
  258. /// Get [`Proofs`] by state
  259. async fn get_proofs_by_keyset_id(
  260. &self,
  261. keyset_id: &Id,
  262. ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
  263. }
  264. #[async_trait]
  265. /// Mint Signatures Transaction trait
  266. pub trait SignaturesTransaction<'a> {
  267. /// Mint Signature Database Error
  268. type Err: Into<Error> + From<Error>;
  269. /// Add [`BlindSignature`]
  270. async fn add_blind_signatures(
  271. &mut self,
  272. blinded_messages: &[PublicKey],
  273. blind_signatures: &[BlindSignature],
  274. quote_id: Option<QuoteId>,
  275. ) -> Result<(), Self::Err>;
  276. /// Get [`BlindSignature`]s
  277. async fn get_blind_signatures(
  278. &mut self,
  279. blinded_messages: &[PublicKey],
  280. ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
  281. }
  282. #[async_trait]
  283. /// Mint Signatures Database trait
  284. pub trait SignaturesDatabase {
  285. /// Mint Signature Database Error
  286. type Err: Into<Error> + From<Error>;
  287. /// Get [`BlindSignature`]s
  288. async fn get_blind_signatures(
  289. &self,
  290. blinded_messages: &[PublicKey],
  291. ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
  292. /// Get [`BlindSignature`]s for keyset_id
  293. async fn get_blind_signatures_for_keyset(
  294. &self,
  295. keyset_id: &Id,
  296. ) -> Result<Vec<BlindSignature>, Self::Err>;
  297. /// Get [`BlindSignature`]s for quote
  298. async fn get_blind_signatures_for_quote(
  299. &self,
  300. quote_id: &QuoteId,
  301. ) -> Result<Vec<BlindSignature>, Self::Err>;
  302. }
  303. #[async_trait]
  304. /// Commit and Rollback
  305. pub trait DbTransactionFinalizer {
  306. /// Mint Signature Database Error
  307. type Err: Into<Error> + From<Error>;
  308. /// Commits all the changes into the database
  309. async fn commit(self: Box<Self>) -> Result<(), Self::Err>;
  310. /// Rollbacks the write transaction
  311. async fn rollback(self: Box<Self>) -> Result<(), Self::Err>;
  312. }
  313. /// Key-Value Store Transaction trait
  314. #[async_trait]
  315. pub trait KVStoreTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
  316. /// Read value from key-value store
  317. async fn kv_read(
  318. &mut self,
  319. primary_namespace: &str,
  320. secondary_namespace: &str,
  321. key: &str,
  322. ) -> Result<Option<Vec<u8>>, Error>;
  323. /// Write value to key-value store
  324. async fn kv_write(
  325. &mut self,
  326. primary_namespace: &str,
  327. secondary_namespace: &str,
  328. key: &str,
  329. value: &[u8],
  330. ) -> Result<(), Error>;
  331. /// Remove value from key-value store
  332. async fn kv_remove(
  333. &mut self,
  334. primary_namespace: &str,
  335. secondary_namespace: &str,
  336. key: &str,
  337. ) -> Result<(), Error>;
  338. /// List keys in a namespace
  339. async fn kv_list(
  340. &mut self,
  341. primary_namespace: &str,
  342. secondary_namespace: &str,
  343. ) -> Result<Vec<String>, Error>;
  344. }
  345. /// Base database writer
  346. pub trait Transaction<'a, Error>:
  347. DbTransactionFinalizer<Err = Error>
  348. + QuotesTransaction<'a, Err = Error>
  349. + SignaturesTransaction<'a, Err = Error>
  350. + ProofsTransaction<'a, Err = Error>
  351. + KVStoreTransaction<'a, Error>
  352. {
  353. }
  354. /// Key-Value Store Database trait
  355. #[async_trait]
  356. pub trait KVStoreDatabase {
  357. /// KV Store Database Error
  358. type Err: Into<Error> + From<Error>;
  359. /// Read value from key-value store
  360. async fn kv_read(
  361. &self,
  362. primary_namespace: &str,
  363. secondary_namespace: &str,
  364. key: &str,
  365. ) -> Result<Option<Vec<u8>>, Self::Err>;
  366. /// List keys in a namespace
  367. async fn kv_list(
  368. &self,
  369. primary_namespace: &str,
  370. secondary_namespace: &str,
  371. ) -> Result<Vec<String>, Self::Err>;
  372. }
  373. /// Key-Value Store Database trait
  374. #[async_trait]
  375. pub trait KVStore: KVStoreDatabase {
  376. /// Beings a KV transaction
  377. async fn begin_transaction<'a>(
  378. &'a self,
  379. ) -> Result<Box<dyn KVStoreTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
  380. }
  381. /// Type alias for Mint Kv store
  382. pub type DynMintKVStore = std::sync::Arc<dyn KVStore<Err = Error> + Send + Sync>;
  383. /// Mint Database trait
  384. #[async_trait]
  385. pub trait Database<Error>:
  386. KVStoreDatabase<Err = Error>
  387. + QuotesDatabase<Err = Error>
  388. + ProofsDatabase<Err = Error>
  389. + SignaturesDatabase<Err = Error>
  390. {
  391. /// Beings a transaction
  392. async fn begin_transaction<'a>(
  393. &'a self,
  394. ) -> Result<Box<dyn Transaction<'a, Error> + Send + Sync + 'a>, Error>;
  395. }
  396. /// Type alias for Mint Database
  397. pub type DynMintDatabase = std::sync::Arc<dyn Database<Error> + Send + Sync>;