mod.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. //! SQLite Mint
  2. use std::collections::HashMap;
  3. use std::path::Path;
  4. use std::str::FromStr;
  5. use async_trait::async_trait;
  6. use bitcoin::bip32::DerivationPath;
  7. use cdk::cdk_database::{self, MintDatabase};
  8. use cdk::mint::{MintKeySetInfo, MintQuote};
  9. use cdk::nuts::nut05::QuoteState;
  10. use cdk::nuts::{
  11. BlindSignature, CurrencyUnit, Id, MeltQuoteState, MintQuoteState, Proof, Proofs, PublicKey,
  12. };
  13. use cdk::secret::Secret;
  14. use cdk::{mint, Amount};
  15. use error::Error;
  16. use lightning_invoice::Bolt11Invoice;
  17. use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqliteRow};
  18. use sqlx::{ConnectOptions, Row};
  19. pub mod error;
  20. /// Mint SQLite Database
  21. #[derive(Debug, Clone)]
  22. pub struct MintSqliteDatabase {
  23. pool: SqlitePool,
  24. }
  25. impl MintSqliteDatabase {
  26. /// Create new [`MintSqliteDatabase`]
  27. pub async fn new(path: &Path) -> Result<Self, Error> {
  28. let path = path.to_str().ok_or(Error::InvalidDbPath)?;
  29. let _conn = SqliteConnectOptions::from_str(path)?
  30. .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
  31. .read_only(false)
  32. .create_if_missing(true)
  33. .auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full)
  34. .connect()
  35. .await?;
  36. let pool = SqlitePool::connect(path).await?;
  37. Ok(Self { pool })
  38. }
  39. /// Migrate [`MintSqliteDatabase`]
  40. pub async fn migrate(&self) {
  41. sqlx::migrate!("./src/mint/migrations")
  42. .run(&self.pool)
  43. .await
  44. .expect("Could not run migrations");
  45. }
  46. }
  47. #[async_trait]
  48. impl MintDatabase for MintSqliteDatabase {
  49. type Err = cdk_database::Error;
  50. async fn add_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
  51. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  52. sqlx::query(
  53. r#"
  54. UPDATE keyset
  55. SET active=FALSE
  56. WHERE unit IS ?;
  57. "#,
  58. )
  59. .bind(unit.to_string())
  60. .bind(id.to_string())
  61. .execute(&mut transaction)
  62. .await
  63. .map_err(Error::from)?;
  64. sqlx::query(
  65. r#"
  66. UPDATE keyset
  67. SET active=TRUE
  68. WHERE unit IS ?
  69. AND id IS ?;
  70. "#,
  71. )
  72. .bind(unit.to_string())
  73. .bind(id.to_string())
  74. .execute(&mut transaction)
  75. .await
  76. .map_err(Error::from)?;
  77. transaction.commit().await.map_err(Error::from)?;
  78. Ok(())
  79. }
  80. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err> {
  81. let rec = sqlx::query(
  82. r#"
  83. SELECT id
  84. FROM keyset
  85. WHERE active = 1
  86. AND unit IS ?
  87. "#,
  88. )
  89. .bind(unit.to_string())
  90. .fetch_one(&self.pool)
  91. .await;
  92. let rec = match rec {
  93. Ok(rec) => rec,
  94. Err(err) => match err {
  95. sqlx::Error::RowNotFound => return Ok(None),
  96. _ => return Err(Error::SQLX(err).into()),
  97. },
  98. };
  99. Ok(Some(
  100. Id::from_str(rec.try_get("id").map_err(Error::from)?).map_err(Error::from)?,
  101. ))
  102. }
  103. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err> {
  104. let recs = sqlx::query(
  105. r#"
  106. SELECT id, unit
  107. FROM keyset
  108. WHERE active = 1
  109. "#,
  110. )
  111. .fetch_all(&self.pool)
  112. .await
  113. // TODO: should check if error is not found and return none
  114. .map_err(Error::from)?;
  115. let keysets = recs
  116. .iter()
  117. .filter_map(|r| match Id::from_str(r.get("id")) {
  118. Ok(id) => Some((
  119. CurrencyUnit::from_str(r.get::<'_, &str, &str>("unit")).unwrap(),
  120. id,
  121. )),
  122. Err(_) => None,
  123. })
  124. .collect();
  125. Ok(keysets)
  126. }
  127. async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
  128. sqlx::query(
  129. r#"
  130. INSERT OR REPLACE INTO mint_quote
  131. (id, mint_url, amount, unit, request, state, expiry, request_lookup_id)
  132. VALUES (?, ?, ?, ?, ?, ?, ?, ?);
  133. "#,
  134. )
  135. .bind(quote.id.to_string())
  136. .bind(quote.mint_url.to_string())
  137. .bind(u64::from(quote.amount) as i64)
  138. .bind(quote.unit.to_string())
  139. .bind(quote.request)
  140. .bind(quote.state.to_string())
  141. .bind(quote.expiry as i64)
  142. .bind(quote.request_lookup_id)
  143. .execute(&self.pool)
  144. .await
  145. // TODO: should check if error is not found and return none
  146. .map_err(Error::from)?;
  147. Ok(())
  148. }
  149. async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
  150. let rec = sqlx::query(
  151. r#"
  152. SELECT *
  153. FROM mint_quote
  154. WHERE id=?;
  155. "#,
  156. )
  157. .bind(quote_id)
  158. .fetch_one(&self.pool)
  159. .await;
  160. let rec = match rec {
  161. Ok(rec) => rec,
  162. Err(err) => match err {
  163. sqlx::Error::RowNotFound => return Ok(None),
  164. _ => return Err(Error::SQLX(err).into()),
  165. },
  166. };
  167. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  168. }
  169. async fn get_mint_quote_by_request(
  170. &self,
  171. request: &str,
  172. ) -> Result<Option<MintQuote>, Self::Err> {
  173. let rec = sqlx::query(
  174. r#"
  175. SELECT *
  176. FROM mint_quote
  177. WHERE request=?;
  178. "#,
  179. )
  180. .bind(request)
  181. .fetch_one(&self.pool)
  182. .await;
  183. let rec = match rec {
  184. Ok(rec) => rec,
  185. Err(err) => match err {
  186. sqlx::Error::RowNotFound => return Ok(None),
  187. _ => return Err(Error::SQLX(err).into()),
  188. },
  189. };
  190. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  191. }
  192. async fn get_mint_quote_by_request_lookup_id(
  193. &self,
  194. request_lookup_id: &str,
  195. ) -> Result<Option<MintQuote>, Self::Err> {
  196. let rec = sqlx::query(
  197. r#"
  198. SELECT *
  199. FROM mint_quote
  200. WHERE request_lookup_id=?;
  201. "#,
  202. )
  203. .bind(request_lookup_id)
  204. .fetch_one(&self.pool)
  205. .await;
  206. let rec = match rec {
  207. Ok(rec) => rec,
  208. Err(err) => match err {
  209. sqlx::Error::RowNotFound => return Ok(None),
  210. _ => return Err(Error::SQLX(err).into()),
  211. },
  212. };
  213. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  214. }
  215. async fn update_mint_quote_state(
  216. &self,
  217. quote_id: &str,
  218. state: MintQuoteState,
  219. ) -> Result<MintQuoteState, Self::Err> {
  220. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  221. let rec = sqlx::query(
  222. r#"
  223. SELECT *
  224. FROM mint_quote
  225. WHERE id=?;
  226. "#,
  227. )
  228. .bind(quote_id)
  229. .fetch_one(&mut transaction)
  230. .await
  231. .map_err(Error::from)?;
  232. let quote = sqlite_row_to_mint_quote(rec)?;
  233. sqlx::query(
  234. r#"
  235. UPDATE mint_quote SET state = ? WHERE id = ?
  236. "#,
  237. )
  238. .bind(state.to_string())
  239. .bind(quote_id)
  240. .execute(&mut transaction)
  241. .await
  242. .map_err(Error::from)?;
  243. transaction.commit().await.map_err(Error::from)?;
  244. Ok(quote.state)
  245. }
  246. async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
  247. let rec = sqlx::query(
  248. r#"
  249. SELECT *
  250. FROM mint_quote
  251. "#,
  252. )
  253. .fetch_all(&self.pool)
  254. .await
  255. .map_err(Error::from)?;
  256. let mint_quotes = rec.into_iter().flat_map(sqlite_row_to_mint_quote).collect();
  257. Ok(mint_quotes)
  258. }
  259. async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  260. sqlx::query(
  261. r#"
  262. DELETE FROM mint_quote
  263. WHERE id=?
  264. "#,
  265. )
  266. .bind(quote_id)
  267. .execute(&self.pool)
  268. .await
  269. .map_err(Error::from)?;
  270. Ok(())
  271. }
  272. async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err> {
  273. sqlx::query(
  274. r#"
  275. INSERT OR REPLACE INTO melt_quote
  276. (id, unit, amount, request, fee_reserve, state, expiry, payment_preimage, request_lookup_id)
  277. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
  278. "#,
  279. )
  280. .bind(quote.id.to_string())
  281. .bind(quote.unit.to_string())
  282. .bind(u64::from(quote.amount) as i64)
  283. .bind(quote.request)
  284. .bind(u64::from(quote.fee_reserve) as i64)
  285. .bind(quote.state.to_string())
  286. .bind(quote.expiry as i64)
  287. .bind(quote.payment_preimage)
  288. .bind(quote.request_lookup_id)
  289. .execute(&self.pool)
  290. .await
  291. .map_err(Error::from)?;
  292. Ok(())
  293. }
  294. async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<mint::MeltQuote>, Self::Err> {
  295. let rec = sqlx::query(
  296. r#"
  297. SELECT *
  298. FROM melt_quote
  299. WHERE id=?;
  300. "#,
  301. )
  302. .bind(quote_id)
  303. .fetch_one(&self.pool)
  304. .await;
  305. let rec = match rec {
  306. Ok(rec) => rec,
  307. Err(err) => match err {
  308. sqlx::Error::RowNotFound => return Ok(None),
  309. _ => return Err(Error::SQLX(err).into()),
  310. },
  311. };
  312. Ok(Some(sqlite_row_to_melt_quote(rec)?))
  313. }
  314. async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err> {
  315. let rec = sqlx::query(
  316. r#"
  317. SELECT *
  318. FROM melt_quote
  319. "#,
  320. )
  321. .fetch_all(&self.pool)
  322. .await
  323. .map_err(Error::from)?;
  324. let melt_quotes = rec.into_iter().flat_map(sqlite_row_to_melt_quote).collect();
  325. Ok(melt_quotes)
  326. }
  327. async fn update_melt_quote_state(
  328. &self,
  329. quote_id: &str,
  330. state: MeltQuoteState,
  331. ) -> Result<MeltQuoteState, Self::Err> {
  332. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  333. let rec = sqlx::query(
  334. r#"
  335. SELECT *
  336. FROM melt_quote
  337. WHERE id=?;
  338. "#,
  339. )
  340. .bind(quote_id)
  341. .fetch_one(&mut transaction)
  342. .await
  343. .map_err(Error::from)?;
  344. let quote = sqlite_row_to_melt_quote(rec)?;
  345. sqlx::query(
  346. r#"
  347. UPDATE melt_quote SET state = ? WHERE id = ?
  348. "#,
  349. )
  350. .bind(state.to_string())
  351. .bind(quote_id)
  352. .execute(&mut transaction)
  353. .await
  354. .map_err(Error::from)?;
  355. transaction.commit().await.map_err(Error::from)?;
  356. Ok(quote.state)
  357. }
  358. async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  359. sqlx::query(
  360. r#"
  361. DELETE FROM melt_quote
  362. WHERE id=?
  363. "#,
  364. )
  365. .bind(quote_id)
  366. .execute(&self.pool)
  367. .await
  368. .map_err(Error::from)?;
  369. Ok(())
  370. }
  371. async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> {
  372. sqlx::query(
  373. r#"
  374. INSERT OR REPLACE INTO keyset
  375. (id, unit, active, valid_from, valid_to, derivation_path, max_order, input_fee_ppk, derivation_path_index)
  376. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
  377. "#,
  378. )
  379. .bind(keyset.id.to_string())
  380. .bind(keyset.unit.to_string())
  381. .bind(keyset.active)
  382. .bind(keyset.valid_from as i64)
  383. .bind(keyset.valid_to.map(|v| v as i64))
  384. .bind(keyset.derivation_path.to_string())
  385. .bind(keyset.max_order)
  386. .bind(keyset.input_fee_ppk as i64)
  387. .bind(keyset.derivation_path_index)
  388. .execute(&self.pool)
  389. .await
  390. .map_err(Error::from)?;
  391. Ok(())
  392. }
  393. async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> {
  394. let rec = sqlx::query(
  395. r#"
  396. SELECT *
  397. FROM keyset
  398. WHERE id=?;
  399. "#,
  400. )
  401. .bind(id.to_string())
  402. .fetch_one(&self.pool)
  403. .await;
  404. let rec = match rec {
  405. Ok(rec) => rec,
  406. Err(err) => match err {
  407. sqlx::Error::RowNotFound => return Ok(None),
  408. _ => return Err(Error::SQLX(err).into()),
  409. },
  410. };
  411. Ok(Some(sqlite_row_to_keyset_info(rec)?))
  412. }
  413. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> {
  414. let recs = sqlx::query(
  415. r#"
  416. SELECT *
  417. FROM keyset;
  418. "#,
  419. )
  420. .fetch_all(&self.pool)
  421. .await
  422. .map_err(Error::from)?;
  423. Ok(recs
  424. .into_iter()
  425. .flat_map(sqlite_row_to_keyset_info)
  426. .collect())
  427. }
  428. async fn add_spent_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
  429. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  430. for proof in proofs {
  431. sqlx::query(
  432. r#"
  433. INSERT OR REPLACE INTO proof
  434. (y, amount, keyset_id, secret, c, witness, state)
  435. VALUES (?, ?, ?, ?, ?, ?, ?);
  436. "#,
  437. )
  438. .bind(proof.y()?.to_bytes().to_vec())
  439. .bind(u64::from(proof.amount) as i64)
  440. .bind(proof.keyset_id.to_string())
  441. .bind(proof.secret.to_string())
  442. .bind(proof.c.to_bytes().to_vec())
  443. .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
  444. .bind("SPENT")
  445. .execute(&mut transaction)
  446. .await
  447. .map_err(Error::from)?;
  448. }
  449. transaction.commit().await.map_err(Error::from)?;
  450. Ok(())
  451. }
  452. async fn get_spent_proofs_by_secrets(
  453. &self,
  454. secrets: &[Secret],
  455. ) -> Result<Vec<Option<Proof>>, Self::Err> {
  456. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  457. let mut proofs = Vec::with_capacity(secrets.len());
  458. for secret in secrets {
  459. let rec = sqlx::query(
  460. r#"
  461. SELECT *
  462. FROM proof
  463. WHERE secret=?
  464. AND state="SPENT";
  465. "#,
  466. )
  467. .bind(secret.to_string())
  468. .fetch_one(&mut transaction)
  469. .await;
  470. match rec {
  471. Ok(rec) => {
  472. proofs.push(Some(sqlite_row_to_proof(rec)?));
  473. }
  474. Err(err) => match err {
  475. sqlx::Error::RowNotFound => proofs.push(None),
  476. _ => return Err(Error::SQLX(err).into()),
  477. },
  478. };
  479. }
  480. transaction.commit().await.map_err(Error::from)?;
  481. Ok(proofs)
  482. }
  483. async fn get_spent_proofs_by_ys(
  484. &self,
  485. ys: &[PublicKey],
  486. ) -> Result<Vec<Option<Proof>>, Self::Err> {
  487. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  488. let mut proofs = Vec::with_capacity(ys.len());
  489. for y in ys {
  490. let rec = sqlx::query(
  491. r#"
  492. SELECT *
  493. FROM proof
  494. WHERE y=?
  495. AND state="SPENT";
  496. "#,
  497. )
  498. .bind(y.to_bytes().to_vec())
  499. .fetch_one(&mut transaction)
  500. .await;
  501. match rec {
  502. Ok(rec) => {
  503. proofs.push(Some(sqlite_row_to_proof(rec)?));
  504. }
  505. Err(err) => match err {
  506. sqlx::Error::RowNotFound => proofs.push(None),
  507. _ => return Err(Error::SQLX(err).into()),
  508. },
  509. };
  510. }
  511. transaction.commit().await.map_err(Error::from)?;
  512. Ok(proofs)
  513. }
  514. async fn add_pending_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
  515. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  516. for proof in proofs {
  517. sqlx::query(
  518. r#"
  519. INSERT OR REPLACE INTO proof
  520. (y, amount, keyset_id, secret, c, witness, state)
  521. VALUES (?, ?, ?, ?, ?, ?, ?);
  522. "#,
  523. )
  524. .bind(proof.y()?.to_bytes().to_vec())
  525. .bind(u64::from(proof.amount) as i64)
  526. .bind(proof.keyset_id.to_string())
  527. .bind(proof.secret.to_string())
  528. .bind(proof.c.to_bytes().to_vec())
  529. .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
  530. .bind("PENDING")
  531. .execute(&mut transaction)
  532. .await
  533. .map_err(Error::from)?;
  534. }
  535. transaction.commit().await.map_err(Error::from)?;
  536. Ok(())
  537. }
  538. async fn get_pending_proofs_by_secrets(
  539. &self,
  540. secrets: &[Secret],
  541. ) -> Result<Vec<Option<Proof>>, Self::Err> {
  542. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  543. let mut proofs = Vec::with_capacity(secrets.len());
  544. for secret in secrets {
  545. let rec = sqlx::query(
  546. r#"
  547. SELECT *
  548. FROM proof
  549. WHERE secret=?
  550. AND state="PENDING";
  551. "#,
  552. )
  553. .bind(secret.to_string())
  554. .fetch_one(&mut transaction)
  555. .await;
  556. match rec {
  557. Ok(rec) => {
  558. proofs.push(Some(sqlite_row_to_proof(rec)?));
  559. }
  560. Err(err) => match err {
  561. sqlx::Error::RowNotFound => proofs.push(None),
  562. _ => return Err(Error::SQLX(err).into()),
  563. },
  564. };
  565. }
  566. transaction.commit().await.map_err(Error::from)?;
  567. Ok(proofs)
  568. }
  569. async fn get_pending_proofs_by_ys(
  570. &self,
  571. ys: &[PublicKey],
  572. ) -> Result<Vec<Option<Proof>>, Self::Err> {
  573. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  574. let mut proofs = Vec::with_capacity(ys.len());
  575. for y in ys {
  576. let rec = sqlx::query(
  577. r#"
  578. SELECT *
  579. FROM proof
  580. WHERE y=?
  581. AND state="PENDING";
  582. "#,
  583. )
  584. .bind(y.to_bytes().to_vec())
  585. .fetch_one(&mut transaction)
  586. .await;
  587. match rec {
  588. Ok(rec) => {
  589. proofs.push(Some(sqlite_row_to_proof(rec)?));
  590. }
  591. Err(err) => match err {
  592. sqlx::Error::RowNotFound => proofs.push(None),
  593. _ => return Err(Error::SQLX(err).into()),
  594. },
  595. };
  596. }
  597. Ok(proofs)
  598. }
  599. async fn remove_pending_proofs(&self, secrets: Vec<&Secret>) -> Result<(), Self::Err> {
  600. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  601. for secret in secrets {
  602. sqlx::query(
  603. r#"
  604. DELETE FROM proof
  605. WHERE secret=?
  606. AND state="PENDING";
  607. "#,
  608. )
  609. .bind(secret.to_string())
  610. .execute(&mut transaction)
  611. .await
  612. .map_err(Error::from)?;
  613. }
  614. transaction.commit().await.map_err(Error::from)?;
  615. Ok(())
  616. }
  617. async fn add_blind_signatures(
  618. &self,
  619. blinded_messages: &[PublicKey],
  620. blinded_signatures: &[BlindSignature],
  621. ) -> Result<(), Self::Err> {
  622. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  623. for (message, signature) in blinded_messages.iter().zip(blinded_signatures) {
  624. sqlx::query(
  625. r#"
  626. INSERT INTO blind_signature
  627. (y, amount, keyset_id, c)
  628. VALUES (?, ?, ?, ?);
  629. "#,
  630. )
  631. .bind(message.to_bytes().to_vec())
  632. .bind(u64::from(signature.amount) as i64)
  633. .bind(signature.keyset_id.to_string())
  634. .bind(signature.c.to_bytes().to_vec())
  635. .execute(&mut transaction)
  636. .await
  637. .map_err(Error::from)?;
  638. }
  639. transaction.commit().await.map_err(Error::from)?;
  640. Ok(())
  641. }
  642. async fn get_blinded_signature(
  643. &self,
  644. blinded_message: &PublicKey,
  645. ) -> Result<Option<BlindSignature>, Self::Err> {
  646. let rec = sqlx::query(
  647. r#"
  648. SELECT *
  649. FROM blind_signature
  650. WHERE y=?;
  651. "#,
  652. )
  653. .bind(blinded_message.to_bytes().to_vec())
  654. .fetch_one(&self.pool)
  655. .await;
  656. let rec = match rec {
  657. Ok(rec) => rec,
  658. Err(err) => match err {
  659. sqlx::Error::RowNotFound => return Ok(None),
  660. _ => return Err(Error::SQLX(err).into()),
  661. },
  662. };
  663. Ok(Some(sqlite_row_to_blind_signature(rec)?))
  664. }
  665. async fn get_blinded_signatures(
  666. &self,
  667. blinded_messages: Vec<PublicKey>,
  668. ) -> Result<Vec<Option<BlindSignature>>, Self::Err> {
  669. let mut signatures = Vec::with_capacity(blinded_messages.len());
  670. for message in blinded_messages {
  671. let rec = sqlx::query(
  672. r#"
  673. SELECT *
  674. FROM blind_signature
  675. WHERE y=?;
  676. "#,
  677. )
  678. .bind(message.to_bytes().to_vec())
  679. .fetch_one(&self.pool)
  680. .await;
  681. if let Ok(row) = rec {
  682. let blinded = sqlite_row_to_blind_signature(row)?;
  683. signatures.push(Some(blinded));
  684. } else {
  685. signatures.push(None);
  686. }
  687. }
  688. Ok(signatures)
  689. }
  690. }
  691. fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
  692. let row_id: String = row.try_get("id").map_err(Error::from)?;
  693. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  694. let row_active: bool = row.try_get("active").map_err(Error::from)?;
  695. let row_valid_from: i64 = row.try_get("valid_from").map_err(Error::from)?;
  696. let row_valid_to: Option<i64> = row.try_get("valid_to").map_err(Error::from)?;
  697. let row_derivation_path: String = row.try_get("derivation_path").map_err(Error::from)?;
  698. let row_max_order: u8 = row.try_get("max_order").map_err(Error::from)?;
  699. let row_keyset_ppk: Option<i64> = row.try_get("input_fee_ppk").map_err(Error::from)?;
  700. let row_derivation_path_index: Option<i64> =
  701. row.try_get("derivation_path_index").map_err(Error::from)?;
  702. Ok(MintKeySetInfo {
  703. id: Id::from_str(&row_id).map_err(Error::from)?,
  704. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  705. active: row_active,
  706. valid_from: row_valid_from as u64,
  707. valid_to: row_valid_to.map(|v| v as u64),
  708. derivation_path: DerivationPath::from_str(&row_derivation_path).map_err(Error::from)?,
  709. derivation_path_index: row_derivation_path_index.map(|d| d as u32),
  710. max_order: row_max_order,
  711. input_fee_ppk: row_keyset_ppk.unwrap_or(0) as u64,
  712. })
  713. }
  714. fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
  715. let row_id: String = row.try_get("id").map_err(Error::from)?;
  716. let row_mint_url: String = row.try_get("mint_url").map_err(Error::from)?;
  717. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  718. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  719. let row_request: String = row.try_get("request").map_err(Error::from)?;
  720. let row_state: String = row.try_get("state").map_err(Error::from)?;
  721. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  722. let row_request_lookup_id: Option<String> =
  723. row.try_get("request_lookup_id").map_err(Error::from)?;
  724. let request_lookup_id = match row_request_lookup_id {
  725. Some(id) => id,
  726. None => match Bolt11Invoice::from_str(&row_request) {
  727. Ok(invoice) => invoice.payment_hash().to_string(),
  728. Err(_) => row_request.clone(),
  729. },
  730. };
  731. Ok(MintQuote {
  732. id: row_id,
  733. mint_url: row_mint_url.into(),
  734. amount: Amount::from(row_amount as u64),
  735. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  736. request: row_request,
  737. state: MintQuoteState::from_str(&row_state).map_err(Error::from)?,
  738. expiry: row_expiry as u64,
  739. request_lookup_id,
  740. })
  741. }
  742. fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<mint::MeltQuote, Error> {
  743. let row_id: String = row.try_get("id").map_err(Error::from)?;
  744. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  745. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  746. let row_request: String = row.try_get("request").map_err(Error::from)?;
  747. let row_fee_reserve: i64 = row.try_get("fee_reserve").map_err(Error::from)?;
  748. let row_state: String = row.try_get("state").map_err(Error::from)?;
  749. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  750. let row_preimage: Option<String> = row.try_get("payment_preimage").map_err(Error::from)?;
  751. let row_request_lookup: Option<String> =
  752. row.try_get("request_lookup_id").map_err(Error::from)?;
  753. let request_lookup_id = row_request_lookup.unwrap_or(row_request.clone());
  754. Ok(mint::MeltQuote {
  755. id: row_id,
  756. amount: Amount::from(row_amount as u64),
  757. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  758. request: row_request,
  759. fee_reserve: Amount::from(row_fee_reserve as u64),
  760. state: QuoteState::from_str(&row_state)?,
  761. expiry: row_expiry as u64,
  762. payment_preimage: row_preimage,
  763. request_lookup_id,
  764. })
  765. }
  766. fn sqlite_row_to_proof(row: SqliteRow) -> Result<Proof, Error> {
  767. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  768. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  769. let row_secret: String = row.try_get("secret").map_err(Error::from)?;
  770. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  771. let row_witness: Option<String> = row.try_get("witness").map_err(Error::from)?;
  772. Ok(Proof {
  773. amount: Amount::from(row_amount as u64),
  774. keyset_id: Id::from_str(&keyset_id)?,
  775. secret: Secret::from_str(&row_secret)?,
  776. c: PublicKey::from_slice(&row_c)?,
  777. witness: row_witness.and_then(|w| serde_json::from_str(&w).ok()),
  778. dleq: None,
  779. })
  780. }
  781. fn sqlite_row_to_blind_signature(row: SqliteRow) -> Result<BlindSignature, Error> {
  782. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  783. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  784. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  785. Ok(BlindSignature {
  786. amount: Amount::from(row_amount as u64),
  787. keyset_id: Id::from_str(&keyset_id)?,
  788. c: PublicKey::from_slice(&row_c)?,
  789. dleq: None,
  790. })
  791. }