mod.rs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567
  1. //! SQLite Mint
  2. use std::collections::HashMap;
  3. use std::path::Path;
  4. use std::str::FromStr;
  5. use std::time::Duration;
  6. use async_trait::async_trait;
  7. use bitcoin::bip32::DerivationPath;
  8. use cdk_common::common::{LnKey, QuoteTTL};
  9. use cdk_common::database::{self, MintDatabase};
  10. use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
  11. use cdk_common::nut00::ProofsMethods;
  12. use cdk_common::nut05::QuoteState;
  13. use cdk_common::secret::Secret;
  14. use cdk_common::{
  15. Amount, BlindSignature, BlindSignatureDleq, CurrencyUnit, Id, MeltBolt11Request,
  16. MeltQuoteState, MintInfo, MintQuoteState, PaymentMethod, Proof, Proofs, PublicKey, SecretKey,
  17. State,
  18. };
  19. use error::Error;
  20. use lightning_invoice::Bolt11Invoice;
  21. use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions, SqliteRow};
  22. use sqlx::Row;
  23. use uuid::fmt::Hyphenated;
  24. use uuid::Uuid;
  25. pub mod error;
  26. /// Mint SQLite Database
  27. #[derive(Debug, Clone)]
  28. pub struct MintSqliteDatabase {
  29. pool: SqlitePool,
  30. }
  31. impl MintSqliteDatabase {
  32. /// Create new [`MintSqliteDatabase`]
  33. pub async fn new(path: &Path) -> Result<Self, Error> {
  34. let path = path.to_str().ok_or(Error::InvalidDbPath)?;
  35. let db_options = SqliteConnectOptions::from_str(path)?
  36. .busy_timeout(Duration::from_secs(5))
  37. .read_only(false)
  38. .create_if_missing(true)
  39. .auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full);
  40. let pool = SqlitePoolOptions::new()
  41. .max_connections(1)
  42. .connect_with(db_options)
  43. .await?;
  44. Ok(Self { pool })
  45. }
  46. /// Migrate [`MintSqliteDatabase`]
  47. pub async fn migrate(&self) {
  48. sqlx::migrate!("./src/mint/migrations")
  49. .run(&self.pool)
  50. .await
  51. .expect("Could not run migrations");
  52. }
  53. }
  54. #[async_trait]
  55. impl MintDatabase for MintSqliteDatabase {
  56. type Err = database::Error;
  57. async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
  58. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  59. let update_res = sqlx::query(
  60. r#"
  61. UPDATE keyset
  62. SET active=FALSE
  63. WHERE unit IS ?;
  64. "#,
  65. )
  66. .bind(unit.to_string())
  67. .execute(&mut transaction)
  68. .await;
  69. match update_res {
  70. Ok(_) => (),
  71. Err(err) => {
  72. tracing::error!("SQLite Could not update keyset");
  73. if let Err(err) = transaction.rollback().await {
  74. tracing::error!("Could not rollback sql transaction: {}", err);
  75. }
  76. return Err(Error::from(err).into());
  77. }
  78. };
  79. let update_res = sqlx::query(
  80. r#"
  81. UPDATE keyset
  82. SET active=TRUE
  83. WHERE unit IS ?
  84. AND id IS ?;
  85. "#,
  86. )
  87. .bind(unit.to_string())
  88. .bind(id.to_string())
  89. .execute(&mut transaction)
  90. .await;
  91. match update_res {
  92. Ok(_) => (),
  93. Err(err) => {
  94. tracing::error!("SQLite Could not update keyset");
  95. if let Err(err) = transaction.rollback().await {
  96. tracing::error!("Could not rollback sql transaction: {}", err);
  97. }
  98. return Err(Error::from(err).into());
  99. }
  100. };
  101. transaction.commit().await.map_err(Error::from)?;
  102. Ok(())
  103. }
  104. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err> {
  105. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  106. let rec = sqlx::query(
  107. r#"
  108. SELECT id
  109. FROM keyset
  110. WHERE active = 1
  111. AND unit IS ?
  112. "#,
  113. )
  114. .bind(unit.to_string())
  115. .fetch_one(&mut transaction)
  116. .await;
  117. let rec = match rec {
  118. Ok(rec) => {
  119. transaction.commit().await.map_err(Error::from)?;
  120. rec
  121. }
  122. Err(err) => match err {
  123. sqlx::Error::RowNotFound => {
  124. transaction.commit().await.map_err(Error::from)?;
  125. return Ok(None);
  126. }
  127. _ => {
  128. return {
  129. if let Err(err) = transaction.rollback().await {
  130. tracing::error!("Could not rollback sql transaction: {}", err);
  131. }
  132. Err(Error::SQLX(err).into())
  133. }
  134. }
  135. },
  136. };
  137. Ok(Some(
  138. Id::from_str(rec.try_get("id").map_err(Error::from)?).map_err(Error::from)?,
  139. ))
  140. }
  141. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err> {
  142. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  143. let recs = sqlx::query(
  144. r#"
  145. SELECT id, unit
  146. FROM keyset
  147. WHERE active = 1
  148. "#,
  149. )
  150. .fetch_all(&mut transaction)
  151. .await;
  152. match recs {
  153. Ok(recs) => {
  154. transaction.commit().await.map_err(Error::from)?;
  155. let keysets = recs
  156. .iter()
  157. .filter_map(|r| match Id::from_str(r.get("id")) {
  158. Ok(id) => Some((
  159. CurrencyUnit::from_str(r.get::<'_, &str, &str>("unit")).unwrap(),
  160. id,
  161. )),
  162. Err(_) => None,
  163. })
  164. .collect();
  165. Ok(keysets)
  166. }
  167. Err(err) => {
  168. tracing::error!("SQLite could not get active keyset");
  169. if let Err(err) = transaction.rollback().await {
  170. tracing::error!("Could not rollback sql transaction: {}", err);
  171. }
  172. Err(Error::from(err).into())
  173. }
  174. }
  175. }
  176. async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
  177. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  178. let res = sqlx::query(
  179. r#"
  180. INSERT OR REPLACE INTO mint_quote
  181. (id, amount, unit, request, state, expiry, request_lookup_id, pubkey)
  182. VALUES (?, ?, ?, ?, ?, ?, ?, ?);
  183. "#,
  184. )
  185. .bind(quote.id.to_string())
  186. .bind(u64::from(quote.amount) as i64)
  187. .bind(quote.unit.to_string())
  188. .bind(quote.request)
  189. .bind(quote.state.to_string())
  190. .bind(quote.expiry as i64)
  191. .bind(quote.request_lookup_id)
  192. .bind(quote.pubkey.map(|p| p.to_string()))
  193. .execute(&mut transaction)
  194. .await;
  195. match res {
  196. Ok(_) => {
  197. transaction.commit().await.map_err(Error::from)?;
  198. Ok(())
  199. }
  200. Err(err) => {
  201. tracing::error!("SQLite Could not update keyset");
  202. if let Err(err) = transaction.rollback().await {
  203. tracing::error!("Could not rollback sql transaction: {}", err);
  204. }
  205. Err(Error::from(err).into())
  206. }
  207. }
  208. }
  209. async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintQuote>, Self::Err> {
  210. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  211. let rec = sqlx::query(
  212. r#"
  213. SELECT *
  214. FROM mint_quote
  215. WHERE id=?;
  216. "#,
  217. )
  218. .bind(quote_id.as_hyphenated())
  219. .fetch_one(&mut transaction)
  220. .await;
  221. match rec {
  222. Ok(rec) => {
  223. transaction.commit().await.map_err(Error::from)?;
  224. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  225. }
  226. Err(err) => match err {
  227. sqlx::Error::RowNotFound => {
  228. transaction.commit().await.map_err(Error::from)?;
  229. Ok(None)
  230. }
  231. _ => {
  232. if let Err(err) = transaction.rollback().await {
  233. tracing::error!("Could not rollback sql transaction: {}", err);
  234. }
  235. Err(Error::SQLX(err).into())
  236. }
  237. },
  238. }
  239. }
  240. async fn get_mint_quote_by_request(
  241. &self,
  242. request: &str,
  243. ) -> Result<Option<MintQuote>, Self::Err> {
  244. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  245. let rec = sqlx::query(
  246. r#"
  247. SELECT *
  248. FROM mint_quote
  249. WHERE request=?;
  250. "#,
  251. )
  252. .bind(request)
  253. .fetch_one(&mut transaction)
  254. .await;
  255. match rec {
  256. Ok(rec) => {
  257. transaction.commit().await.map_err(Error::from)?;
  258. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  259. }
  260. Err(err) => match err {
  261. sqlx::Error::RowNotFound => {
  262. transaction.commit().await.map_err(Error::from)?;
  263. Ok(None)
  264. }
  265. _ => {
  266. if let Err(err) = transaction.rollback().await {
  267. tracing::error!("Could not rollback sql transaction: {}", err);
  268. }
  269. Err(Error::SQLX(err).into())
  270. }
  271. },
  272. }
  273. }
  274. async fn get_mint_quote_by_request_lookup_id(
  275. &self,
  276. request_lookup_id: &str,
  277. ) -> Result<Option<MintQuote>, Self::Err> {
  278. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  279. let rec = sqlx::query(
  280. r#"
  281. SELECT *
  282. FROM mint_quote
  283. WHERE request_lookup_id=?;
  284. "#,
  285. )
  286. .bind(request_lookup_id)
  287. .fetch_one(&mut transaction)
  288. .await;
  289. match rec {
  290. Ok(rec) => {
  291. transaction.commit().await.map_err(Error::from)?;
  292. Ok(Some(sqlite_row_to_mint_quote(rec)?))
  293. }
  294. Err(err) => match err {
  295. sqlx::Error::RowNotFound => {
  296. transaction.commit().await.map_err(Error::from)?;
  297. Ok(None)
  298. }
  299. _ => {
  300. if let Err(err) = transaction.rollback().await {
  301. tracing::error!("Could not rollback sql transaction: {}", err);
  302. }
  303. Err(Error::SQLX(err).into())
  304. }
  305. },
  306. }
  307. }
  308. async fn update_mint_quote_state(
  309. &self,
  310. quote_id: &Uuid,
  311. state: MintQuoteState,
  312. ) -> Result<MintQuoteState, Self::Err> {
  313. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  314. let rec = sqlx::query(
  315. r#"
  316. SELECT *
  317. FROM mint_quote
  318. WHERE id=?;
  319. "#,
  320. )
  321. .bind(quote_id.as_hyphenated())
  322. .fetch_one(&mut transaction)
  323. .await;
  324. let quote = match rec {
  325. Ok(row) => sqlite_row_to_mint_quote(row)?,
  326. Err(err) => {
  327. tracing::error!("SQLite Could not update keyset");
  328. if let Err(err) = transaction.rollback().await {
  329. tracing::error!("Could not rollback sql transaction: {}", err);
  330. }
  331. return Err(Error::from(err).into());
  332. }
  333. };
  334. let update = sqlx::query(
  335. r#"
  336. UPDATE mint_quote SET state = ? WHERE id = ?
  337. "#,
  338. )
  339. .bind(state.to_string())
  340. .bind(quote_id.as_hyphenated())
  341. .execute(&mut transaction)
  342. .await;
  343. match update {
  344. Ok(_) => {
  345. transaction.commit().await.map_err(Error::from)?;
  346. Ok(quote.state)
  347. }
  348. Err(err) => {
  349. tracing::error!("SQLite Could not update keyset");
  350. if let Err(err) = transaction.rollback().await {
  351. tracing::error!("Could not rollback sql transaction: {}", err);
  352. }
  353. return Err(Error::from(err).into());
  354. }
  355. }
  356. }
  357. async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
  358. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  359. let rec = sqlx::query(
  360. r#"
  361. SELECT *
  362. FROM mint_quote
  363. "#,
  364. )
  365. .fetch_all(&mut transaction)
  366. .await;
  367. match rec {
  368. Ok(rows) => {
  369. transaction.commit().await.map_err(Error::from)?;
  370. let mint_quotes = rows
  371. .into_iter()
  372. .map(sqlite_row_to_mint_quote)
  373. .collect::<Result<Vec<MintQuote>, _>>()?;
  374. Ok(mint_quotes)
  375. }
  376. Err(err) => {
  377. tracing::error!("SQLite get mint quotes");
  378. if let Err(err) = transaction.rollback().await {
  379. tracing::error!("Could not rollback sql transaction: {}", err);
  380. }
  381. return Err(Error::from(err).into());
  382. }
  383. }
  384. }
  385. async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> {
  386. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  387. let res = sqlx::query(
  388. r#"
  389. DELETE FROM mint_quote
  390. WHERE id=?
  391. "#,
  392. )
  393. .bind(quote_id.as_hyphenated())
  394. .execute(&mut transaction)
  395. .await;
  396. match res {
  397. Ok(_) => {
  398. transaction.commit().await.map_err(Error::from)?;
  399. Ok(())
  400. }
  401. Err(err) => {
  402. tracing::error!("SQLite Could not remove mint quote");
  403. if let Err(err) = transaction.rollback().await {
  404. tracing::error!("Could not rollback sql transaction: {}", err);
  405. }
  406. Err(Error::from(err).into())
  407. }
  408. }
  409. }
  410. async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err> {
  411. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  412. let res = sqlx::query(
  413. r#"
  414. INSERT OR REPLACE INTO melt_quote
  415. (id, unit, amount, request, fee_reserve, state, expiry, payment_preimage, request_lookup_id, msat_to_pay)
  416. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
  417. "#,
  418. )
  419. .bind(quote.id.to_string())
  420. .bind(quote.unit.to_string())
  421. .bind(u64::from(quote.amount) as i64)
  422. .bind(quote.request)
  423. .bind(u64::from(quote.fee_reserve) as i64)
  424. .bind(quote.state.to_string())
  425. .bind(quote.expiry as i64)
  426. .bind(quote.payment_preimage)
  427. .bind(quote.request_lookup_id)
  428. .bind(quote.msat_to_pay.map(|a| u64::from(a) as i64))
  429. .execute(&mut transaction)
  430. .await;
  431. match res {
  432. Ok(_) => {
  433. transaction.commit().await.map_err(Error::from)?;
  434. Ok(())
  435. }
  436. Err(err) => {
  437. tracing::error!("SQLite Could not remove mint quote");
  438. if let Err(err) = transaction.rollback().await {
  439. tracing::error!("Could not rollback sql transaction: {}", err);
  440. }
  441. Err(Error::from(err).into())
  442. }
  443. }
  444. }
  445. async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err> {
  446. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  447. let rec = sqlx::query(
  448. r#"
  449. SELECT *
  450. FROM melt_quote
  451. WHERE id=?;
  452. "#,
  453. )
  454. .bind(quote_id.as_hyphenated())
  455. .fetch_one(&mut transaction)
  456. .await;
  457. match rec {
  458. Ok(rec) => {
  459. transaction.commit().await.map_err(Error::from)?;
  460. Ok(Some(sqlite_row_to_melt_quote(rec)?))
  461. }
  462. Err(err) => match err {
  463. sqlx::Error::RowNotFound => {
  464. transaction.commit().await.map_err(Error::from)?;
  465. Ok(None)
  466. }
  467. _ => {
  468. if let Err(err) = transaction.rollback().await {
  469. tracing::error!("Could not rollback sql transaction: {}", err);
  470. }
  471. Err(Error::SQLX(err).into())
  472. }
  473. },
  474. }
  475. }
  476. async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err> {
  477. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  478. let rec = sqlx::query(
  479. r#"
  480. SELECT *
  481. FROM melt_quote
  482. "#,
  483. )
  484. .fetch_all(&mut transaction)
  485. .await
  486. .map_err(Error::from);
  487. match rec {
  488. Ok(rec) => {
  489. let melt_quotes = rec
  490. .into_iter()
  491. .map(sqlite_row_to_melt_quote)
  492. .collect::<Result<Vec<mint::MeltQuote>, _>>()?;
  493. Ok(melt_quotes)
  494. }
  495. Err(err) => {
  496. if let Err(err) = transaction.rollback().await {
  497. tracing::error!("Could not rollback sql transaction: {}", err);
  498. }
  499. Err(err.into())
  500. }
  501. }
  502. }
  503. async fn update_melt_quote_state(
  504. &self,
  505. quote_id: &Uuid,
  506. state: MeltQuoteState,
  507. ) -> Result<MeltQuoteState, Self::Err> {
  508. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  509. let rec = sqlx::query(
  510. r#"
  511. SELECT *
  512. FROM melt_quote
  513. WHERE id=?;
  514. "#,
  515. )
  516. .bind(quote_id.as_hyphenated())
  517. .fetch_one(&mut transaction)
  518. .await;
  519. let quote = match rec {
  520. Ok(rec) => sqlite_row_to_melt_quote(rec)?,
  521. Err(err) => {
  522. tracing::error!("SQLite Could not update keyset");
  523. if let Err(err) = transaction.rollback().await {
  524. tracing::error!("Could not rollback sql transaction: {}", err);
  525. }
  526. return Err(Error::from(err).into());
  527. }
  528. };
  529. let rec = sqlx::query(
  530. r#"
  531. UPDATE melt_quote SET state = ? WHERE id = ?
  532. "#,
  533. )
  534. .bind(state.to_string())
  535. .bind(quote_id.as_hyphenated())
  536. .execute(&mut transaction)
  537. .await;
  538. match rec {
  539. Ok(_) => {
  540. transaction.commit().await.map_err(Error::from)?;
  541. }
  542. Err(err) => {
  543. tracing::error!("SQLite Could not update melt quote");
  544. if let Err(err) = transaction.rollback().await {
  545. tracing::error!("Could not rollback sql transaction: {}", err);
  546. }
  547. return Err(Error::from(err).into());
  548. }
  549. };
  550. Ok(quote.state)
  551. }
  552. async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> {
  553. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  554. let res = sqlx::query(
  555. r#"
  556. DELETE FROM melt_quote
  557. WHERE id=?
  558. "#,
  559. )
  560. .bind(quote_id.as_hyphenated())
  561. .execute(&mut transaction)
  562. .await;
  563. match res {
  564. Ok(_) => {
  565. transaction.commit().await.map_err(Error::from)?;
  566. Ok(())
  567. }
  568. Err(err) => {
  569. tracing::error!("SQLite Could not update melt quote");
  570. if let Err(err) = transaction.rollback().await {
  571. tracing::error!("Could not rollback sql transaction: {}", err);
  572. }
  573. Err(Error::from(err).into())
  574. }
  575. }
  576. }
  577. async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> {
  578. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  579. let res = sqlx::query(
  580. r#"
  581. INSERT OR REPLACE INTO keyset
  582. (id, unit, active, valid_from, valid_to, derivation_path, max_order, input_fee_ppk, derivation_path_index)
  583. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
  584. "#,
  585. )
  586. .bind(keyset.id.to_string())
  587. .bind(keyset.unit.to_string())
  588. .bind(keyset.active)
  589. .bind(keyset.valid_from as i64)
  590. .bind(keyset.valid_to.map(|v| v as i64))
  591. .bind(keyset.derivation_path.to_string())
  592. .bind(keyset.max_order)
  593. .bind(keyset.input_fee_ppk as i64)
  594. .bind(keyset.derivation_path_index)
  595. .execute(&mut transaction)
  596. .await;
  597. match res {
  598. Ok(_) => {
  599. transaction.commit().await.map_err(Error::from)?;
  600. Ok(())
  601. }
  602. Err(err) => {
  603. tracing::error!("SQLite could not add keyset info");
  604. if let Err(err) = transaction.rollback().await {
  605. tracing::error!("Could not rollback sql transaction: {}", err);
  606. }
  607. Err(Error::from(err).into())
  608. }
  609. }
  610. }
  611. async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> {
  612. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  613. let rec = sqlx::query(
  614. r#"
  615. SELECT *
  616. FROM keyset
  617. WHERE id=?;
  618. "#,
  619. )
  620. .bind(id.to_string())
  621. .fetch_one(&mut transaction)
  622. .await;
  623. match rec {
  624. Ok(rec) => {
  625. transaction.commit().await.map_err(Error::from)?;
  626. Ok(Some(sqlite_row_to_keyset_info(rec)?))
  627. }
  628. Err(err) => match err {
  629. sqlx::Error::RowNotFound => {
  630. transaction.commit().await.map_err(Error::from)?;
  631. return Ok(None);
  632. }
  633. _ => {
  634. tracing::error!("SQLite could not get keyset info");
  635. if let Err(err) = transaction.rollback().await {
  636. tracing::error!("Could not rollback sql transaction: {}", err);
  637. }
  638. return Err(Error::SQLX(err).into());
  639. }
  640. },
  641. }
  642. }
  643. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> {
  644. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  645. let recs = sqlx::query(
  646. r#"
  647. SELECT *
  648. FROM keyset;
  649. "#,
  650. )
  651. .fetch_all(&mut transaction)
  652. .await
  653. .map_err(Error::from);
  654. match recs {
  655. Ok(recs) => {
  656. transaction.commit().await.map_err(Error::from)?;
  657. Ok(recs
  658. .into_iter()
  659. .map(sqlite_row_to_keyset_info)
  660. .collect::<Result<_, _>>()?)
  661. }
  662. Err(err) => {
  663. tracing::error!("SQLite could not get keyset info");
  664. if let Err(err) = transaction.rollback().await {
  665. tracing::error!("Could not rollback sql transaction: {}", err);
  666. }
  667. Err(err.into())
  668. }
  669. }
  670. }
  671. async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> {
  672. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  673. for proof in proofs {
  674. if let Err(err) = sqlx::query(
  675. r#"
  676. INSERT INTO proof
  677. (y, amount, keyset_id, secret, c, witness, state, quote_id)
  678. VALUES (?, ?, ?, ?, ?, ?, ?, ?);
  679. "#,
  680. )
  681. .bind(proof.y()?.to_bytes().to_vec())
  682. .bind(u64::from(proof.amount) as i64)
  683. .bind(proof.keyset_id.to_string())
  684. .bind(proof.secret.to_string())
  685. .bind(proof.c.to_bytes().to_vec())
  686. .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
  687. .bind("UNSPENT")
  688. .bind(quote_id.map(|q| q.hyphenated()))
  689. .execute(&mut transaction)
  690. .await
  691. .map_err(Error::from)
  692. {
  693. tracing::debug!("Attempting to add known proof. Skipping.... {:?}", err);
  694. }
  695. }
  696. transaction.commit().await.map_err(Error::from)?;
  697. Ok(())
  698. }
  699. async fn remove_proofs(
  700. &self,
  701. ys: &[PublicKey],
  702. _quote_id: Option<Uuid>,
  703. ) -> Result<(), Self::Err> {
  704. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  705. let sql = format!(
  706. "DELETE FROM proof WHERE y IN ({})",
  707. std::iter::repeat("?")
  708. .take(ys.len())
  709. .collect::<Vec<_>>()
  710. .join(",")
  711. );
  712. ys.iter()
  713. .fold(sqlx::query(&sql), |query, y| {
  714. query.bind(y.to_bytes().to_vec())
  715. })
  716. .execute(&mut transaction)
  717. .await
  718. .map_err(Error::from)?;
  719. transaction.commit().await.map_err(Error::from)?;
  720. Ok(())
  721. }
  722. async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
  723. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  724. let sql = format!(
  725. "SELECT * FROM proof WHERE y IN ({})",
  726. "?,".repeat(ys.len()).trim_end_matches(',')
  727. );
  728. let mut proofs = ys
  729. .iter()
  730. .fold(sqlx::query(&sql), |query, y| {
  731. query.bind(y.to_bytes().to_vec())
  732. })
  733. .fetch_all(&mut transaction)
  734. .await
  735. .map_err(|err| {
  736. tracing::error!("SQLite could not get state of proof: {err:?}");
  737. Error::SQLX(err)
  738. })?
  739. .into_iter()
  740. .map(|row| {
  741. PublicKey::from_slice(row.get("y"))
  742. .map_err(Error::from)
  743. .and_then(|y| sqlite_row_to_proof(row).map(|proof| (y, proof)))
  744. })
  745. .collect::<Result<HashMap<_, _>, _>>()?;
  746. Ok(ys.iter().map(|y| proofs.remove(y)).collect())
  747. }
  748. async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err> {
  749. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  750. let rec = sqlx::query(
  751. r#"
  752. SELECT *
  753. FROM proof
  754. WHERE quote_id=?;
  755. "#,
  756. )
  757. .bind(quote_id.as_hyphenated())
  758. .fetch_all(&mut transaction)
  759. .await;
  760. let ys = match rec {
  761. Ok(rec) => {
  762. transaction.commit().await.map_err(Error::from)?;
  763. let proofs = rec
  764. .into_iter()
  765. .map(sqlite_row_to_proof)
  766. .collect::<Result<Vec<Proof>, _>>()?;
  767. proofs.ys()?
  768. }
  769. Err(err) => match err {
  770. sqlx::Error::RowNotFound => {
  771. transaction.commit().await.map_err(Error::from)?;
  772. vec![]
  773. }
  774. _ => {
  775. if let Err(err) = transaction.rollback().await {
  776. tracing::error!("Could not rollback sql transaction: {}", err);
  777. }
  778. return Err(Error::SQLX(err).into());
  779. }
  780. },
  781. };
  782. Ok(ys)
  783. }
  784. async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err> {
  785. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  786. let sql = format!(
  787. "SELECT y, state FROM proof WHERE y IN ({})",
  788. "?,".repeat(ys.len()).trim_end_matches(',')
  789. );
  790. let mut current_states = ys
  791. .iter()
  792. .fold(sqlx::query(&sql), |query, y| {
  793. query.bind(y.to_bytes().to_vec())
  794. })
  795. .fetch_all(&mut transaction)
  796. .await
  797. .map_err(|err| {
  798. tracing::error!("SQLite could not get state of proof: {err:?}");
  799. Error::SQLX(err)
  800. })?
  801. .into_iter()
  802. .map(|row| {
  803. PublicKey::from_slice(row.get("y"))
  804. .map_err(Error::from)
  805. .and_then(|y| {
  806. let state: String = row.get("state");
  807. State::from_str(&state)
  808. .map_err(Error::from)
  809. .map(|state| (y, state))
  810. })
  811. })
  812. .collect::<Result<HashMap<_, _>, _>>()?;
  813. Ok(ys.iter().map(|y| current_states.remove(y)).collect())
  814. }
  815. async fn get_proofs_by_keyset_id(
  816. &self,
  817. keyset_id: &Id,
  818. ) -> Result<(Proofs, Vec<Option<State>>), Self::Err> {
  819. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  820. let rec = sqlx::query(
  821. r#"
  822. SELECT *
  823. FROM proof
  824. WHERE keyset_id=?;
  825. "#,
  826. )
  827. .bind(keyset_id.to_string())
  828. .fetch_all(&mut transaction)
  829. .await;
  830. match rec {
  831. Ok(rec) => {
  832. transaction.commit().await.map_err(Error::from)?;
  833. let mut proofs_for_id = vec![];
  834. let mut states = vec![];
  835. for row in rec {
  836. let (proof, state) = sqlite_row_to_proof_with_state(row)?;
  837. proofs_for_id.push(proof);
  838. states.push(state);
  839. }
  840. Ok((proofs_for_id, states))
  841. }
  842. Err(err) => {
  843. tracing::error!("SQLite could not get proofs by keysets id");
  844. if let Err(err) = transaction.rollback().await {
  845. tracing::error!("Could not rollback sql transaction: {}", err);
  846. }
  847. return Err(Error::from(err).into());
  848. }
  849. }
  850. }
  851. async fn update_proofs_states(
  852. &self,
  853. ys: &[PublicKey],
  854. proofs_state: State,
  855. ) -> Result<Vec<Option<State>>, Self::Err> {
  856. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  857. let sql = format!(
  858. "SELECT y, state FROM proof WHERE y IN ({})",
  859. "?,".repeat(ys.len()).trim_end_matches(',')
  860. );
  861. let mut current_states = ys
  862. .iter()
  863. .fold(sqlx::query(&sql), |query, y| {
  864. query.bind(y.to_bytes().to_vec())
  865. })
  866. .fetch_all(&mut transaction)
  867. .await
  868. .map_err(|err| {
  869. tracing::error!("SQLite could not get state of proof: {err:?}");
  870. Error::SQLX(err)
  871. })?
  872. .into_iter()
  873. .map(|row| {
  874. PublicKey::from_slice(row.get("y"))
  875. .map_err(Error::from)
  876. .and_then(|y| {
  877. let state: String = row.get("state");
  878. State::from_str(&state)
  879. .map_err(Error::from)
  880. .map(|state| (y, state))
  881. })
  882. })
  883. .collect::<Result<HashMap<_, _>, _>>()?;
  884. let update_sql = format!(
  885. "UPDATE proof SET state = ? WHERE state != ? AND y IN ({})",
  886. "?,".repeat(ys.len()).trim_end_matches(',')
  887. );
  888. ys.iter()
  889. .fold(
  890. sqlx::query(&update_sql)
  891. .bind(proofs_state.to_string())
  892. .bind(State::Spent.to_string()),
  893. |query, y| query.bind(y.to_bytes().to_vec()),
  894. )
  895. .execute(&mut transaction)
  896. .await
  897. .map_err(|err| {
  898. tracing::error!("SQLite could not update proof state: {err:?}");
  899. Error::SQLX(err)
  900. })?;
  901. transaction.commit().await.map_err(Error::from)?;
  902. Ok(ys.iter().map(|y| current_states.remove(y)).collect())
  903. }
  904. async fn add_blind_signatures(
  905. &self,
  906. blinded_messages: &[PublicKey],
  907. blinded_signatures: &[BlindSignature],
  908. quote_id: Option<Uuid>,
  909. ) -> Result<(), Self::Err> {
  910. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  911. for (message, signature) in blinded_messages.iter().zip(blinded_signatures) {
  912. let res = sqlx::query(
  913. r#"
  914. INSERT INTO blind_signature
  915. (y, amount, keyset_id, c, quote_id, dleq_e, dleq_s)
  916. VALUES (?, ?, ?, ?, ?, ?, ?);
  917. "#,
  918. )
  919. .bind(message.to_bytes().to_vec())
  920. .bind(u64::from(signature.amount) as i64)
  921. .bind(signature.keyset_id.to_string())
  922. .bind(signature.c.to_bytes().to_vec())
  923. .bind(quote_id.map(|q| q.hyphenated()))
  924. .bind(signature.dleq.as_ref().map(|dleq| dleq.e.to_secret_hex()))
  925. .bind(signature.dleq.as_ref().map(|dleq| dleq.s.to_secret_hex()))
  926. .execute(&mut transaction)
  927. .await;
  928. if let Err(err) = res {
  929. tracing::error!("SQLite could not add blind signature");
  930. if let Err(err) = transaction.rollback().await {
  931. tracing::error!("Could not rollback sql transaction: {}", err);
  932. }
  933. return Err(Error::SQLX(err).into());
  934. }
  935. }
  936. transaction.commit().await.map_err(Error::from)?;
  937. Ok(())
  938. }
  939. async fn get_blind_signatures(
  940. &self,
  941. blinded_messages: &[PublicKey],
  942. ) -> Result<Vec<Option<BlindSignature>>, Self::Err> {
  943. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  944. let sql = format!(
  945. "SELECT * FROM blind_signature WHERE y IN ({})",
  946. "?,".repeat(blinded_messages.len()).trim_end_matches(',')
  947. );
  948. let mut blinded_signatures = blinded_messages
  949. .iter()
  950. .fold(sqlx::query(&sql), |query, y| {
  951. query.bind(y.to_bytes().to_vec())
  952. })
  953. .fetch_all(&mut transaction)
  954. .await
  955. .map_err(|err| {
  956. tracing::error!("SQLite could not get state of proof: {err:?}");
  957. Error::SQLX(err)
  958. })?
  959. .into_iter()
  960. .map(|row| {
  961. PublicKey::from_slice(row.get("y"))
  962. .map_err(Error::from)
  963. .and_then(|y| sqlite_row_to_blind_signature(row).map(|blinded| (y, blinded)))
  964. })
  965. .collect::<Result<HashMap<_, _>, _>>()?;
  966. Ok(blinded_messages
  967. .iter()
  968. .map(|y| blinded_signatures.remove(y))
  969. .collect())
  970. }
  971. async fn get_blind_signatures_for_keyset(
  972. &self,
  973. keyset_id: &Id,
  974. ) -> Result<Vec<BlindSignature>, Self::Err> {
  975. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  976. let rec = sqlx::query(
  977. r#"
  978. SELECT *
  979. FROM blind_signature
  980. WHERE keyset_id=?;
  981. "#,
  982. )
  983. .bind(keyset_id.to_string())
  984. .fetch_all(&mut transaction)
  985. .await;
  986. match rec {
  987. Ok(rec) => {
  988. transaction.commit().await.map_err(Error::from)?;
  989. let sigs = rec
  990. .into_iter()
  991. .map(sqlite_row_to_blind_signature)
  992. .collect::<Result<Vec<BlindSignature>, _>>()?;
  993. Ok(sigs)
  994. }
  995. Err(err) => {
  996. tracing::error!("SQLite could not get vlinf signatures for keyset");
  997. if let Err(err) = transaction.rollback().await {
  998. tracing::error!("Could not rollback sql transaction: {}", err);
  999. }
  1000. return Err(Error::from(err).into());
  1001. }
  1002. }
  1003. }
  1004. async fn add_melt_request(
  1005. &self,
  1006. melt_request: MeltBolt11Request<Uuid>,
  1007. ln_key: LnKey,
  1008. ) -> Result<(), Self::Err> {
  1009. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1010. let res = sqlx::query(
  1011. r#"
  1012. INSERT OR REPLACE INTO melt_request
  1013. (id, inputs, outputs, method, unit)
  1014. VALUES (?, ?, ?, ?, ?);
  1015. "#,
  1016. )
  1017. .bind(melt_request.quote)
  1018. .bind(serde_json::to_string(&melt_request.inputs)?)
  1019. .bind(serde_json::to_string(&melt_request.outputs)?)
  1020. .bind(ln_key.method.to_string())
  1021. .bind(ln_key.unit.to_string())
  1022. .execute(&mut transaction)
  1023. .await;
  1024. match res {
  1025. Ok(_) => {
  1026. transaction.commit().await.map_err(Error::from)?;
  1027. Ok(())
  1028. }
  1029. Err(err) => {
  1030. tracing::error!("SQLite Could not update keyset");
  1031. if let Err(err) = transaction.rollback().await {
  1032. tracing::error!("Could not rollback sql transaction: {}", err);
  1033. }
  1034. Err(Error::from(err).into())
  1035. }
  1036. }
  1037. }
  1038. async fn get_melt_request(
  1039. &self,
  1040. quote_id: &Uuid,
  1041. ) -> Result<Option<(MeltBolt11Request<Uuid>, LnKey)>, Self::Err> {
  1042. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1043. let rec = sqlx::query(
  1044. r#"
  1045. SELECT *
  1046. FROM melt_request
  1047. WHERE id=?;
  1048. "#,
  1049. )
  1050. .bind(quote_id.as_hyphenated())
  1051. .fetch_one(&mut transaction)
  1052. .await;
  1053. match rec {
  1054. Ok(rec) => {
  1055. transaction.commit().await.map_err(Error::from)?;
  1056. let (request, key) = sqlite_row_to_melt_request(rec)?;
  1057. Ok(Some((request, key)))
  1058. }
  1059. Err(err) => match err {
  1060. sqlx::Error::RowNotFound => {
  1061. transaction.commit().await.map_err(Error::from)?;
  1062. return Ok(None);
  1063. }
  1064. _ => {
  1065. return {
  1066. if let Err(err) = transaction.rollback().await {
  1067. tracing::error!("Could not rollback sql transaction: {}", err);
  1068. }
  1069. Err(Error::SQLX(err).into())
  1070. }
  1071. }
  1072. },
  1073. }
  1074. }
  1075. /// Get [`BlindSignature`]s for quote
  1076. async fn get_blind_signatures_for_quote(
  1077. &self,
  1078. quote_id: &Uuid,
  1079. ) -> Result<Vec<BlindSignature>, Self::Err> {
  1080. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1081. let recs = sqlx::query(
  1082. r#"
  1083. SELECT *
  1084. FROM blind_signature
  1085. WHERE quote_id=?;
  1086. "#,
  1087. )
  1088. .bind(quote_id.as_hyphenated())
  1089. .fetch_all(&mut transaction)
  1090. .await;
  1091. match recs {
  1092. Ok(recs) => {
  1093. transaction.commit().await.map_err(Error::from)?;
  1094. let keysets = recs
  1095. .into_iter()
  1096. .map(sqlite_row_to_blind_signature)
  1097. .collect::<Result<Vec<_>, _>>()?;
  1098. Ok(keysets)
  1099. }
  1100. Err(err) => {
  1101. tracing::error!("SQLite could not get active keyset");
  1102. if let Err(err) = transaction.rollback().await {
  1103. tracing::error!("Could not rollback sql transaction: {}", err);
  1104. }
  1105. Err(Error::from(err).into())
  1106. }
  1107. }
  1108. }
  1109. async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err> {
  1110. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1111. let res = sqlx::query(
  1112. r#"
  1113. INSERT OR REPLACE INTO config
  1114. (id, value)
  1115. VALUES (?, ?);
  1116. "#,
  1117. )
  1118. .bind("mint_info")
  1119. .bind(serde_json::to_string(&mint_info)?)
  1120. .execute(&mut transaction)
  1121. .await;
  1122. match res {
  1123. Ok(_) => {
  1124. transaction.commit().await.map_err(Error::from)?;
  1125. Ok(())
  1126. }
  1127. Err(err) => {
  1128. tracing::error!("SQLite Could not update mint info");
  1129. if let Err(err) = transaction.rollback().await {
  1130. tracing::error!("Could not rollback sql transaction: {}", err);
  1131. }
  1132. Err(Error::from(err).into())
  1133. }
  1134. }
  1135. }
  1136. async fn get_mint_info(&self) -> Result<MintInfo, Self::Err> {
  1137. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1138. let rec = sqlx::query(
  1139. r#"
  1140. SELECT *
  1141. FROM config
  1142. WHERE id=?;
  1143. "#,
  1144. )
  1145. .bind("mint_info")
  1146. .fetch_one(&mut transaction)
  1147. .await;
  1148. match rec {
  1149. Ok(rec) => {
  1150. transaction.commit().await.map_err(Error::from)?;
  1151. let value: String = rec.try_get("value").map_err(Error::from)?;
  1152. let mint_info = serde_json::from_str(&value)?;
  1153. Ok(mint_info)
  1154. }
  1155. Err(err) => match err {
  1156. sqlx::Error::RowNotFound => {
  1157. transaction.commit().await.map_err(Error::from)?;
  1158. return Err(Error::UnknownMintInfo.into());
  1159. }
  1160. _ => {
  1161. return {
  1162. if let Err(err) = transaction.rollback().await {
  1163. tracing::error!("Could not rollback sql transaction: {}", err);
  1164. }
  1165. Err(Error::SQLX(err).into())
  1166. }
  1167. }
  1168. },
  1169. }
  1170. }
  1171. async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> {
  1172. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1173. let res = sqlx::query(
  1174. r#"
  1175. INSERT OR REPLACE INTO config
  1176. (id, value)
  1177. VALUES (?, ?);
  1178. "#,
  1179. )
  1180. .bind("quote_ttl")
  1181. .bind(serde_json::to_string(&quote_ttl)?)
  1182. .execute(&mut transaction)
  1183. .await;
  1184. match res {
  1185. Ok(_) => {
  1186. transaction.commit().await.map_err(Error::from)?;
  1187. Ok(())
  1188. }
  1189. Err(err) => {
  1190. tracing::error!("SQLite Could not update mint info");
  1191. if let Err(err) = transaction.rollback().await {
  1192. tracing::error!("Could not rollback sql transaction: {}", err);
  1193. }
  1194. Err(Error::from(err).into())
  1195. }
  1196. }
  1197. }
  1198. async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> {
  1199. let mut transaction = self.pool.begin().await.map_err(Error::from)?;
  1200. let rec = sqlx::query(
  1201. r#"
  1202. SELECT *
  1203. FROM config
  1204. WHERE id=?;
  1205. "#,
  1206. )
  1207. .bind("quote_ttl")
  1208. .fetch_one(&mut transaction)
  1209. .await;
  1210. match rec {
  1211. Ok(rec) => {
  1212. transaction.commit().await.map_err(Error::from)?;
  1213. let value: String = rec.try_get("value").map_err(Error::from)?;
  1214. let quote_ttl = serde_json::from_str(&value)?;
  1215. Ok(quote_ttl)
  1216. }
  1217. Err(err) => match err {
  1218. sqlx::Error::RowNotFound => {
  1219. transaction.commit().await.map_err(Error::from)?;
  1220. return Err(Error::UnknownQuoteTTL.into());
  1221. }
  1222. _ => {
  1223. return {
  1224. if let Err(err) = transaction.rollback().await {
  1225. tracing::error!("Could not rollback sql transaction: {}", err);
  1226. }
  1227. Err(Error::SQLX(err).into())
  1228. }
  1229. }
  1230. },
  1231. }
  1232. }
  1233. }
  1234. fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
  1235. let row_id: String = row.try_get("id").map_err(Error::from)?;
  1236. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  1237. let row_active: bool = row.try_get("active").map_err(Error::from)?;
  1238. let row_valid_from: i64 = row.try_get("valid_from").map_err(Error::from)?;
  1239. let row_valid_to: Option<i64> = row.try_get("valid_to").map_err(Error::from)?;
  1240. let row_derivation_path: String = row.try_get("derivation_path").map_err(Error::from)?;
  1241. let row_max_order: u8 = row.try_get("max_order").map_err(Error::from)?;
  1242. let row_keyset_ppk: Option<i64> = row.try_get("input_fee_ppk").map_err(Error::from)?;
  1243. let row_derivation_path_index: Option<i64> =
  1244. row.try_get("derivation_path_index").map_err(Error::from)?;
  1245. Ok(MintKeySetInfo {
  1246. id: Id::from_str(&row_id).map_err(Error::from)?,
  1247. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  1248. active: row_active,
  1249. valid_from: row_valid_from as u64,
  1250. valid_to: row_valid_to.map(|v| v as u64),
  1251. derivation_path: DerivationPath::from_str(&row_derivation_path).map_err(Error::from)?,
  1252. derivation_path_index: row_derivation_path_index.map(|d| d as u32),
  1253. max_order: row_max_order,
  1254. input_fee_ppk: row_keyset_ppk.unwrap_or(0) as u64,
  1255. })
  1256. }
  1257. fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
  1258. let row_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
  1259. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  1260. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  1261. let row_request: String = row.try_get("request").map_err(Error::from)?;
  1262. let row_state: String = row.try_get("state").map_err(Error::from)?;
  1263. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  1264. let row_request_lookup_id: Option<String> =
  1265. row.try_get("request_lookup_id").map_err(Error::from)?;
  1266. let row_pubkey: Option<String> = row.try_get("pubkey").map_err(Error::from)?;
  1267. let request_lookup_id = match row_request_lookup_id {
  1268. Some(id) => id,
  1269. None => match Bolt11Invoice::from_str(&row_request) {
  1270. Ok(invoice) => invoice.payment_hash().to_string(),
  1271. Err(_) => row_request.clone(),
  1272. },
  1273. };
  1274. let pubkey = row_pubkey
  1275. .map(|key| PublicKey::from_str(&key))
  1276. .transpose()?;
  1277. Ok(MintQuote {
  1278. id: row_id.into_uuid(),
  1279. amount: Amount::from(row_amount as u64),
  1280. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  1281. request: row_request,
  1282. state: MintQuoteState::from_str(&row_state).map_err(Error::from)?,
  1283. expiry: row_expiry as u64,
  1284. request_lookup_id,
  1285. pubkey,
  1286. })
  1287. }
  1288. fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<mint::MeltQuote, Error> {
  1289. let row_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
  1290. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  1291. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  1292. let row_request: String = row.try_get("request").map_err(Error::from)?;
  1293. let row_fee_reserve: i64 = row.try_get("fee_reserve").map_err(Error::from)?;
  1294. let row_state: String = row.try_get("state").map_err(Error::from)?;
  1295. let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?;
  1296. let row_preimage: Option<String> = row.try_get("payment_preimage").map_err(Error::from)?;
  1297. let row_request_lookup: Option<String> =
  1298. row.try_get("request_lookup_id").map_err(Error::from)?;
  1299. let request_lookup_id = row_request_lookup.unwrap_or(row_request.clone());
  1300. let row_msat_to_pay: Option<i64> = row.try_get("msat_to_pay").map_err(Error::from)?;
  1301. Ok(mint::MeltQuote {
  1302. id: row_id.into_uuid(),
  1303. amount: Amount::from(row_amount as u64),
  1304. unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
  1305. request: row_request,
  1306. fee_reserve: Amount::from(row_fee_reserve as u64),
  1307. state: QuoteState::from_str(&row_state)?,
  1308. expiry: row_expiry as u64,
  1309. payment_preimage: row_preimage,
  1310. request_lookup_id,
  1311. msat_to_pay: row_msat_to_pay.map(|a| Amount::from(a as u64)),
  1312. })
  1313. }
  1314. fn sqlite_row_to_proof(row: SqliteRow) -> Result<Proof, Error> {
  1315. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  1316. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  1317. let row_secret: String = row.try_get("secret").map_err(Error::from)?;
  1318. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  1319. let row_witness: Option<String> = row.try_get("witness").map_err(Error::from)?;
  1320. Ok(Proof {
  1321. amount: Amount::from(row_amount as u64),
  1322. keyset_id: Id::from_str(&keyset_id)?,
  1323. secret: Secret::from_str(&row_secret)?,
  1324. c: PublicKey::from_slice(&row_c)?,
  1325. witness: row_witness.and_then(|w| serde_json::from_str(&w).ok()),
  1326. dleq: None,
  1327. })
  1328. }
  1329. fn sqlite_row_to_proof_with_state(row: SqliteRow) -> Result<(Proof, Option<State>), Error> {
  1330. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  1331. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  1332. let row_secret: String = row.try_get("secret").map_err(Error::from)?;
  1333. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  1334. let row_witness: Option<String> = row.try_get("witness").map_err(Error::from)?;
  1335. let row_state: Option<String> = row.try_get("state").map_err(Error::from)?;
  1336. let state = row_state.and_then(|s| State::from_str(&s).ok());
  1337. Ok((
  1338. Proof {
  1339. amount: Amount::from(row_amount as u64),
  1340. keyset_id: Id::from_str(&keyset_id)?,
  1341. secret: Secret::from_str(&row_secret)?,
  1342. c: PublicKey::from_slice(&row_c)?,
  1343. witness: row_witness.and_then(|w| serde_json::from_str(&w).ok()),
  1344. dleq: None,
  1345. },
  1346. state,
  1347. ))
  1348. }
  1349. fn sqlite_row_to_blind_signature(row: SqliteRow) -> Result<BlindSignature, Error> {
  1350. let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
  1351. let keyset_id: String = row.try_get("keyset_id").map_err(Error::from)?;
  1352. let row_c: Vec<u8> = row.try_get("c").map_err(Error::from)?;
  1353. let row_dleq_e: Option<String> = row.try_get("dleq_e").map_err(Error::from)?;
  1354. let row_dleq_s: Option<String> = row.try_get("dleq_s").map_err(Error::from)?;
  1355. let dleq = match (row_dleq_e, row_dleq_s) {
  1356. (Some(e), Some(s)) => Some(BlindSignatureDleq {
  1357. e: SecretKey::from_hex(e)?,
  1358. s: SecretKey::from_hex(s)?,
  1359. }),
  1360. _ => None,
  1361. };
  1362. Ok(BlindSignature {
  1363. amount: Amount::from(row_amount as u64),
  1364. keyset_id: Id::from_str(&keyset_id)?,
  1365. c: PublicKey::from_slice(&row_c)?,
  1366. dleq,
  1367. })
  1368. }
  1369. fn sqlite_row_to_melt_request(row: SqliteRow) -> Result<(MeltBolt11Request<Uuid>, LnKey), Error> {
  1370. let quote_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
  1371. let row_inputs: String = row.try_get("inputs").map_err(Error::from)?;
  1372. let row_outputs: Option<String> = row.try_get("outputs").map_err(Error::from)?;
  1373. let row_method: String = row.try_get("method").map_err(Error::from)?;
  1374. let row_unit: String = row.try_get("unit").map_err(Error::from)?;
  1375. let melt_request = MeltBolt11Request {
  1376. quote: quote_id.into_uuid(),
  1377. inputs: serde_json::from_str(&row_inputs)?,
  1378. outputs: row_outputs.and_then(|o| serde_json::from_str(&o).ok()),
  1379. };
  1380. let ln_key = LnKey {
  1381. unit: CurrencyUnit::from_str(&row_unit)?,
  1382. method: PaymentMethod::from_str(&row_method)?,
  1383. };
  1384. Ok((melt_request, ln_key))
  1385. }