mod.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. //! SQLite
  2. use std::collections::HashMap;
  3. use std::str::FromStr;
  4. use async_trait::async_trait;
  5. use bitcoin::bip32::DerivationPath;
  6. use cdk::cdk_database::{self, MintDatabase};
  7. use cdk::mint::MintKeySetInfo;
  8. use cdk::nuts::{BlindSignature, CurrencyUnit, Id, Proof, PublicKey};
  9. use cdk::secret::Secret;
  10. use cdk::types::{MeltQuote, MintQuote};
  11. use cdk::Amount;
  12. use error::Error;
  13. use migration::init_migration;
  14. use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqliteRow};
  15. use sqlx::{ConnectOptions, Row};
  16. pub mod error;
  17. mod migration;
  18. #[derive(Debug, Clone)]
  19. pub struct MintSqliteDatabase {
  20. pool: SqlitePool,
  21. }
  22. impl MintSqliteDatabase {
  23. pub async fn new(path: &str) -> Result<Self, Error> {
  24. let _conn = SqliteConnectOptions::from_str(path)?
  25. .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
  26. .read_only(false)
  27. .create_if_missing(true)
  28. .auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full)
  29. .connect()
  30. .await?;
  31. let pool = SqlitePool::connect(path).await?;
  32. init_migration(&pool).await?;
  33. Ok(Self { pool })
  34. }
  35. }
  36. #[async_trait]
  37. impl MintDatabase for MintSqliteDatabase {
  38. type Err = cdk_database::Error;
  39. async fn add_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
  40. sqlx::query(
  41. r#"
  42. UPDATE keyset
  43. SET active=TRUE
  44. WHERE unit IS ?
  45. AND id IS ?;
  46. "#,
  47. )
  48. .bind(unit.to_string())
  49. .bind(id.to_string())
  50. .execute(&self.pool)
  51. .await
  52. // TODO: should check if error is not found and return none
  53. .map_err(Error::from)?;
  54. Ok(())
  55. }
  56. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err> {
  57. let rec = sqlx::query(
  58. r#"
  59. SELECT id
  60. FROM keyset
  61. WHERE active = 1
  62. AND unit IS ?
  63. "#,
  64. )
  65. .bind(unit.to_string())
  66. .fetch_one(&self.pool)
  67. .await;
  68. let rec = match rec {
  69. Ok(rec) => rec,
  70. Err(err) => match err {
  71. sqlx::Error::RowNotFound => return Ok(None),
  72. _ => return Err(Error::SQLX(err).into()),
  73. },
  74. };
  75. Ok(Some(
  76. Id::from_str(rec.try_get("id").map_err(Error::from)?).map_err(Error::from)?,
  77. ))
  78. }
  79. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err> {
  80. let recs = sqlx::query(
  81. r#"
  82. SELECT id, unit
  83. FROM keyset
  84. WHERE active = 1
  85. "#,
  86. )
  87. .fetch_all(&self.pool)
  88. .await
  89. // TODO: should check if error is not found and return none
  90. .map_err(Error::from)?;
  91. let keysets = recs
  92. .iter()
  93. .filter_map(|r| match Id::from_str(r.get("id")) {
  94. Ok(id) => Some((CurrencyUnit::from(r.get::<'_, &str, &str>("unit")), id)),
  95. Err(_) => None,
  96. })
  97. .collect();
  98. Ok(keysets)
  99. }
  100. async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
  101. sqlx::query(
  102. r#"
  103. INSERT OR REPLACE INTO mint_quote
  104. (id, mint_url, amount, unit, request, paid, expiry)
  105. VALUES (?, ?, ?, ?, ?, ?, ?);
  106. "#,
  107. )
  108. .bind(quote.id.to_string())
  109. .bind(quote.mint_url.to_string())
  110. .bind(u64::from(quote.amount) as i64)
  111. .bind(quote.unit.to_string())
  112. .bind(quote.request)
  113. .bind(quote.paid)
  114. .bind(quote.expiry as i64)
  115. .execute(&self.pool)
  116. .await
  117. // TODO: should check if error is not found and return none
  118. .map_err(Error::from)?;
  119. Ok(())
  120. }
  121. async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
  122. let rec = sqlx::query(
  123. r#"
  124. SELECT *
  125. FROM mint_quote
  126. WHERE id=?;
  127. "#,
  128. )
  129. .bind(quote_id)
  130. .fetch_one(&self.pool)
  131. .await;
  132. let rec = match rec {
  133. Ok(rec) => rec,
  134. Err(err) => match err {
  135. sqlx::Error::RowNotFound => return Ok(None),
  136. _ => return Err(Error::SQLX(err).into()),
  137. },
  138. };
  139. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  140. }
  141. async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
  142. let rec = sqlx::query(
  143. r#"
  144. SELECT *
  145. FROM mint_quote
  146. "#,
  147. )
  148. .fetch_all(&self.pool)
  149. .await
  150. .map_err(Error::from)?;
  151. let mint_quotes = rec.into_iter().flat_map(sqlite_row_to_mint_quote).collect();
  152. Ok(mint_quotes)
  153. }
  154. async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  155. sqlx::query(
  156. r#"
  157. DELETE FROM mint_quote
  158. WHERE id=?
  159. "#,
  160. )
  161. .bind(quote_id)
  162. .execute(&self.pool)
  163. .await
  164. .map_err(Error::from)?;
  165. Ok(())
  166. }
  167. async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), Self::Err> {
  168. sqlx::query(
  169. r#"
  170. INSERT OR REPLACE INTO melt_quote
  171. (id, unit, amount, request, fee_reserve, paid, expiry)
  172. VALUES (?, ?, ?, ?, ?, ?, ?);
  173. "#,
  174. )
  175. .bind(quote.id.to_string())
  176. .bind(quote.unit.to_string())
  177. .bind(u64::from(quote.amount) as i64)
  178. .bind(quote.request)
  179. .bind(u64::from(quote.fee_reserve) as i64)
  180. .bind(quote.paid)
  181. .bind(quote.expiry as i64)
  182. .execute(&self.pool)
  183. .await
  184. .map_err(Error::from)?;
  185. Ok(())
  186. }
  187. async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<MeltQuote>, Self::Err> {
  188. let rec = sqlx::query(
  189. r#"
  190. SELECT *
  191. FROM melt_quote
  192. WHERE id=?;
  193. "#,
  194. )
  195. .bind(quote_id)
  196. .fetch_one(&self.pool)
  197. .await;
  198. let rec = match rec {
  199. Ok(rec) => rec,
  200. Err(err) => match err {
  201. sqlx::Error::RowNotFound => return Ok(None),
  202. _ => return Err(Error::SQLX(err).into()),
  203. },
  204. };
  205. Ok(Some(sqlite_row_to_melt_quote(rec)?))
  206. }
  207. async fn get_melt_quotes(&self) -> Result<Vec<MeltQuote>, Self::Err> {
  208. let rec = sqlx::query(
  209. r#"
  210. SELECT *
  211. FROM melt_quote
  212. "#,
  213. )
  214. .fetch_all(&self.pool)
  215. .await
  216. .map_err(Error::from)?;
  217. let melt_quotes = rec.into_iter().flat_map(sqlite_row_to_melt_quote).collect();
  218. Ok(melt_quotes)
  219. }
  220. async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  221. sqlx::query(
  222. r#"
  223. DELETE FROM melt_quote
  224. WHERE id=?
  225. "#,
  226. )
  227. .bind(quote_id)
  228. .execute(&self.pool)
  229. .await
  230. .map_err(Error::from)?;
  231. Ok(())
  232. }
  233. async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> {
  234. sqlx::query(
  235. r#"
  236. INSERT INTO keyset
  237. (id, unit, active, valid_from, valid_to, derivation_path, max_order)
  238. VALUES (?, ?, ?, ?, ?, ?, ?);
  239. "#,
  240. )
  241. .bind(keyset.id.to_string())
  242. .bind(keyset.unit.to_string())
  243. .bind(keyset.active)
  244. .bind(keyset.valid_from as i64)
  245. .bind(keyset.valid_to.map(|v| v as i64))
  246. .bind(keyset.derivation_path.to_string())
  247. .bind(keyset.max_order)
  248. .execute(&self.pool)
  249. .await
  250. .map_err(Error::from)?;
  251. Ok(())
  252. }
  253. async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> {
  254. let rec = sqlx::query(
  255. r#"
  256. SELECT *
  257. FROM keyset
  258. WHERE id=?;
  259. "#,
  260. )
  261. .bind(id.to_string())
  262. .fetch_one(&self.pool)
  263. .await;
  264. let rec = match rec {
  265. Ok(rec) => rec,
  266. Err(err) => match err {
  267. sqlx::Error::RowNotFound => return Ok(None),
  268. _ => return Err(Error::SQLX(err).into()),
  269. },
  270. };
  271. Ok(Some(sqlite_row_to_keyset_info(rec)?))
  272. }
  273. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> {
  274. let recs = sqlx::query(
  275. r#"
  276. SELECT *
  277. FROM keyset;
  278. "#,
  279. )
  280. .fetch_all(&self.pool)
  281. .await
  282. .map_err(Error::from)?;
  283. Ok(recs
  284. .into_iter()
  285. .flat_map(sqlite_row_to_keyset_info)
  286. .collect())
  287. }
  288. async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err> {
  289. sqlx::query(
  290. r#"
  291. INSERT OR REPLACE INTO proof
  292. (y, amount, keyset_id, secret, c, witness, state)
  293. VALUES (?, ?, ?, ?, ?, ?, ?);
  294. "#,
  295. )
  296. .bind(proof.y()?.to_bytes().to_vec())
  297. .bind(u64::from(proof.amount) as i64)
  298. .bind(proof.keyset_id.to_string())
  299. .bind(proof.secret.to_string())
  300. .bind(proof.c.to_bytes().to_vec())
  301. .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
  302. .bind("SPENT")
  303. .execute(&self.pool)
  304. .await
  305. .map_err(Error::from)?;
  306. Ok(())
  307. }
  308. async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Self::Err> {
  309. let rec = sqlx::query(
  310. r#"
  311. SELECT *
  312. FROM proof
  313. WHERE secret=?
  314. AND state="SPENT";
  315. "#,
  316. )
  317. .bind(secret.to_string())
  318. .fetch_one(&self.pool)
  319. .await;
  320. let rec = match rec {
  321. Ok(rec) => rec,
  322. Err(err) => match err {
  323. sqlx::Error::RowNotFound => return Ok(None),
  324. _ => return Err(Error::SQLX(err).into()),
  325. },
  326. };
  327. Ok(Some(sqlite_row_to_proof(rec)?))
  328. }
  329. async fn get_spent_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err> {
  330. let rec = sqlx::query(
  331. r#"
  332. SELECT *
  333. FROM proof
  334. WHERE y=?
  335. AND state="SPENT";
  336. "#,
  337. )
  338. .bind(y.to_bytes().to_vec())
  339. .fetch_one(&self.pool)
  340. .await;
  341. let rec = match rec {
  342. Ok(rec) => rec,
  343. Err(err) => match err {
  344. sqlx::Error::RowNotFound => return Ok(None),
  345. _ => return Err(Error::SQLX(err).into()),
  346. },
  347. };
  348. Ok(Some(sqlite_row_to_proof(rec)?))
  349. }
  350. async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err> {
  351. sqlx::query(
  352. r#"
  353. INSERT OR REPLACE INTO proof
  354. (y, amount, keyset_id, secret, c, witness, spent, pending)
  355. VALUES (?, ?, ?, ?, ?, ?, ?);
  356. "#,
  357. )
  358. .bind(proof.y()?.to_bytes().to_vec())
  359. .bind(u64::from(proof.amount) as i64)
  360. .bind(proof.keyset_id.to_string())
  361. .bind(proof.secret.to_string())
  362. .bind(proof.c.to_bytes().to_vec())
  363. .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
  364. .bind("PENDING")
  365. .execute(&self.pool)
  366. .await
  367. .map_err(Error::from)?;
  368. Ok(())
  369. }
  370. async fn get_pending_proof_by_secret(
  371. &self,
  372. secret: &Secret,
  373. ) -> Result<Option<Proof>, Self::Err> {
  374. let rec = sqlx::query(
  375. r#"
  376. SELECT *
  377. FROM proof
  378. WHERE secret=?
  379. AND state="PENDING";
  380. "#,
  381. )
  382. .bind(secret.to_string())
  383. .fetch_one(&self.pool)
  384. .await;
  385. let rec = match rec {
  386. Ok(rec) => rec,
  387. Err(err) => match err {
  388. sqlx::Error::RowNotFound => return Ok(None),
  389. _ => return Err(Error::SQLX(err).into()),
  390. },
  391. };
  392. Ok(Some(sqlite_row_to_proof(rec)?))
  393. }
  394. async fn get_pending_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err> {
  395. let rec = sqlx::query(
  396. r#"
  397. SELECT *
  398. FROM proof
  399. WHERE y=?
  400. AND state="PENDING";
  401. "#,
  402. )
  403. .bind(y.to_bytes().to_vec())
  404. .fetch_one(&self.pool)
  405. .await;
  406. let rec = match rec {
  407. Ok(rec) => rec,
  408. Err(err) => match err {
  409. sqlx::Error::RowNotFound => return Ok(None),
  410. _ => return Err(Error::SQLX(err).into()),
  411. },
  412. };
  413. Ok(Some(sqlite_row_to_proof(rec)?))
  414. }
  415. async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err> {
  416. sqlx::query(
  417. r#"
  418. DELETE FROM proof
  419. WHERE secret=?
  420. AND state="PENDING";
  421. "#,
  422. )
  423. .bind(secret.to_string())
  424. .execute(&self.pool)
  425. .await
  426. .map_err(Error::from)?;
  427. Ok(())
  428. }
  429. async fn add_blinded_signature(
  430. &self,
  431. blinded_message: PublicKey,
  432. blinded_signature: BlindSignature,
  433. ) -> Result<(), Self::Err> {
  434. sqlx::query(
  435. r#"
  436. INSERT INTO blind_signature
  437. (y, amount, keyset_id, c)
  438. VALUES (?, ?, ?, ?);
  439. "#,
  440. )
  441. .bind(blinded_message.to_bytes().to_vec())
  442. .bind(u64::from(blinded_signature.amount) as i64)
  443. .bind(blinded_signature.keyset_id.to_string())
  444. .bind(blinded_signature.c.to_bytes().to_vec())
  445. .execute(&self.pool)
  446. .await
  447. .map_err(Error::from)?;
  448. Ok(())
  449. }
  450. async fn get_blinded_signature(
  451. &self,
  452. blinded_message: &PublicKey,
  453. ) -> Result<Option<BlindSignature>, Self::Err> {
  454. let rec = sqlx::query(
  455. r#"
  456. SELECT *
  457. FROM blind_signature
  458. WHERE y=?;
  459. "#,
  460. )
  461. .bind(blinded_message.to_bytes().to_vec())
  462. .fetch_one(&self.pool)
  463. .await;
  464. let rec = match rec {
  465. Ok(rec) => rec,
  466. Err(err) => match err {
  467. sqlx::Error::RowNotFound => return Ok(None),
  468. _ => return Err(Error::SQLX(err).into()),
  469. },
  470. };
  471. Ok(Some(sqlite_row_to_blind_signature(rec)?))
  472. }
  473. async fn get_blinded_signatures(
  474. &self,
  475. blinded_messages: Vec<PublicKey>,
  476. ) -> Result<Vec<Option<BlindSignature>>, Self::Err> {
  477. let mut signatures = Vec::with_capacity(blinded_messages.len());
  478. for message in blinded_messages {
  479. let rec = sqlx::query(
  480. r#"
  481. SELECT *
  482. FROM blind_signature
  483. WHERE y=?;
  484. "#,
  485. )
  486. .bind(message.to_bytes().to_vec())
  487. .fetch_one(&self.pool)
  488. .await;
  489. if let Ok(row) = rec {
  490. let blinded = sqlite_row_to_blind_signature(row)?;
  491. signatures.push(Some(blinded));
  492. } else {
  493. signatures.push(None);
  494. }
  495. }
  496. Ok(signatures)
  497. }
  498. }
  499. fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
  500. let row_id: String = row.try_get("id").map_err(Error::from)?;
  501. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  502. let row_active: bool = row.try_get("active").map_err(Error::from)?;
  503. let row_valid_from: i64 = row.try_get("valid_from").map_err(Error::from)?;
  504. let row_valid_to: Option<i64> = row.try_get("valid_to").map_err(Error::from)?;
  505. let row_derivation_path: String = row.try_get("derivation_path").map_err(Error::from)?;
  506. let row_max_order: u8 = row.try_get("max_order").map_err(Error::from)?;
  507. Ok(MintKeySetInfo {
  508. id: Id::from_str(&row_id).map_err(Error::from)?,
  509. unit: CurrencyUnit::from(&row_unit),
  510. active: row_active,
  511. valid_from: row_valid_from as u64,
  512. valid_to: row_valid_to.map(|v| v as u64),
  513. derivation_path: DerivationPath::from_str(&row_derivation_path).map_err(Error::from)?,
  514. max_order: row_max_order,
  515. })
  516. }
  517. fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
  518. let row_id: String = row.try_get("id").map_err(Error::from)?;
  519. let row_mint_url: String = row.try_get("mint_url").map_err(Error::from)?;
  520. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  521. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  522. let row_request: String = row.try_get("request").map_err(Error::from)?;
  523. let row_paid: bool = row.try_get("paid").map_err(Error::from)?;
  524. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  525. Ok(MintQuote {
  526. id: row_id,
  527. mint_url: row_mint_url.into(),
  528. amount: Amount::from(row_amount as u64),
  529. unit: CurrencyUnit::from(row_unit),
  530. request: row_request,
  531. paid: row_paid,
  532. expiry: row_expiry as u64,
  533. })
  534. }
  535. fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<MeltQuote, Error> {
  536. let row_id: String = row.try_get("id").map_err(Error::from)?;
  537. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  538. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  539. let row_request: String = row.try_get("request").map_err(Error::from)?;
  540. let row_fee_reserve: i64 = row.try_get("fee_reserve").map_err(Error::from)?;
  541. let row_paid: bool = row.try_get("paid").map_err(Error::from)?;
  542. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  543. Ok(MeltQuote {
  544. id: row_id,
  545. amount: Amount::from(row_amount as u64),
  546. unit: CurrencyUnit::from(row_unit),
  547. request: row_request,
  548. fee_reserve: Amount::from(row_fee_reserve as u64),
  549. paid: row_paid,
  550. expiry: row_expiry as u64,
  551. })
  552. }
  553. fn sqlite_row_to_proof(row: SqliteRow) -> Result<Proof, Error> {
  554. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  555. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  556. let row_secret: String = row.try_get("secret").map_err(Error::from)?;
  557. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  558. let row_witness: Option<String> = row.try_get("witness").map_err(Error::from)?;
  559. Ok(Proof {
  560. amount: Amount::from(row_amount as u64),
  561. keyset_id: Id::from_str(&keyset_id)?,
  562. secret: Secret::from_str(&row_secret)?,
  563. c: PublicKey::from_slice(&row_c)?,
  564. witness: row_witness.and_then(|w| serde_json::from_str(&w).ok()),
  565. dleq: None,
  566. })
  567. }
  568. fn sqlite_row_to_blind_signature(row: SqliteRow) -> Result<BlindSignature, Error> {
  569. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  570. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  571. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  572. Ok(BlindSignature {
  573. amount: Amount::from(row_amount as u64),
  574. keyset_id: Id::from_str(&keyset_id)?,
  575. c: PublicKey::from_slice(&row_c)?,
  576. dleq: None,
  577. })
  578. }