mod.rs 57 KB

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